Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 39 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# hyprfocus

a plugin which provides focus animations for us borderless folks, originally inspired by [flashfocus](https://github.com/fennerm/flashfocus)!
A plugin which provides focus animations for us borderless folks, originally inspired by [flashfocus](https://github.com/fennerm/flashfocus)!
Modified to work with the latest Hyprland and support hyprpm as well as some other improvements.

## animations
Expand All @@ -18,43 +18,47 @@ shrink
instructions based on [the official wiki](https://wiki.hyprland.org/Plugins/Using-Plugins/#compiling-official-plugins)

```
hyprpm add https://github.com/pyt0xic/hyprfocus
hyprpm add https://github.com/daxisunder/hyprfocus
hyprpm enable hyprfocus
```

## getting started

to start using hyprfocus, add this to your hyprland config:

```
hyprfocus {
enabled = yes
animate_floating = yes
animate_workspacechange = yes
focus_animation = shrink
# Beziers for focus animations
bezier = bezIn, 0.5,0.0,1.0,0.5
bezier = bezOut, 0.0,0.5,0.5,1.0
bezier = overshot, 0.05, 0.9, 0.1, 1.05
bezier = smoothOut, 0.36, 0, 0.66, -0.56
bezier = smoothIn, 0.25, 1, 0.5, 1
bezier = realsmooth, 0.28,0.29,.69,1.08
# Flash settings
flash {
flash_opacity = 0.95
in_bezier = realsmooth
in_speed = 0.5
out_bezier = realsmooth
out_speed = 3
}
# Shrink settings
shrink {
shrink_percentage = 0.95
in_bezier = realsmooth
in_speed = 1
out_bezier = realsmooth
out_speed = 2
}
plugin {
hyprfocus {
enabled = yes
animate_floating = no
animate_workspacechange = no
focus_animation = flash
# Beziers for focus animations
bezier = bezIn, 0.5, 0.0, 1.0, 0.5
bezier = bezOut, 0.0, 0.5, 0.5, 1.0
bezier = overshot, 0.05, 0.9, 0.1, 1.05
bezier = smoothOut, 0.36, 0, 0.66, -0.56
bezier = smoothIn, 0.25, 1, 0.5, 1
bezier = realsmooth, 0.28, 0.29, 0.69, 1.08
bezier = easeInOutBack, 0.68, -0.6, 0.32, 1.6
# Flash settings
flash {
flash_opacity = 0.7
in_bezier = bezIn
in_speed = 0.5
out_bezier = bezOut
out_speed = 3
}
# Shrink settings
shrink {
shrink_percentage = 0.99
in_bezier = easeInOutBack
in_speed = 1.5
out_bezier = easeInOutBack
out_speed = 3
}
}
}
```

### plugin configuration
Expand All @@ -72,9 +76,11 @@ to start using hyprfocus, add this to your hyprland config:
animations can be configured within the plugin scope with the following syntax:

```
plugin:hyprfocus {
<animation> {
plugin {
hyprfocus {
<animation> {

}
}
}
```
Expand Down Expand Up @@ -109,3 +115,4 @@ bind = $mod, space, animatefocused

- [flashfocus](https://github.com/fennerm/flashfocus): An earlier project of similar nature
- [Original repo](https://github.com/VortexCoyote/hyprfocus.git)
- [upstream](https://github.com/pyt0xic/hyprfocus)
16 changes: 8 additions & 8 deletions hyprpm.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
[repository]
name = "hyprfocus"
authors = ["VortexCoyote, OakleyCord, vaxerski, DRAGONTOS, pyt0xic"]
authors = ["VortexCoyote, OakleyCord, vaxerski, DRAGONTOS, pyt0xic, alyanser, noisethanks, avih7531"]

[hyprfocus]
description = "a focus animation plugin for Hyprland inspired by Flashfocus (pyt0xic fork)"
authors = ["VortexCoyote, OakleyCord, vaxerski, DRAGONTOS, pyt0xic"]
# authors = ["VortexCoyote, OakleyCord, vaxerski, DRAGONTOS, pyt0xic, alyanser, noisethanks, avih7531"]
output = "hyprfocus.so"
commit_pins = [
["1c460e98f870676b15871fe4e5bfeb1a32a3d6d8", "2af0c1e87e3cdcef3c8f9c7def918982312d0b75"],
["c5e28ebcfe00a510922779b2c568cfa52a317445", "c5e28ebcfe00a510922779b2c568cfa52a317445"],
["0c513ba91bd73106be99e35b1a020d24e5ae874a", "e44b956dd4b7507489219bd2b02a3886d547b7e2"],
["cba1ade848feac44b2eda677503900639581c3f4", "49dbe19e08f963e01ac4ba17b42719956d390ec7"],
]
# commit_pins = [
# ["1c460e98f870676b15871fe4e5bfeb1a32a3d6d8", "2af0c1e87e3cdcef3c8f9c7def918982312d0b75"],
# ["c5e28ebcfe00a510922779b2c568cfa52a317445", "c5e28ebcfe00a510922779b2c568cfa52a317445"],
# ["0c513ba91bd73106be99e35b1a020d24e5ae874a", "e44b956dd4b7507489219bd2b02a3886d547b7e2"],
# ["cba1ade848feac44b2eda677503900639581c3f4", "49dbe19e08f963e01ac4ba17b42719956d390ec7"],
# ]
build = [
"make all"
]
15 changes: 6 additions & 9 deletions src/Flash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

#include <hyprland/src/Compositor.hpp>
#include <hyprland/src/desktop/Window.hpp>
#include <hyprland/src/managers/AnimationManager.hpp>
#include <hyprland/src/managers/animation/AnimationManager.hpp>
#include <hyprland/src/plugins/PluginAPI.hpp>

void CFlash::init(HANDLE pHandle, std::string animationName) {
Expand Down Expand Up @@ -33,17 +33,14 @@ void CFlash::onWindowFocus(PHLWINDOW pWindow, HANDLE pHandle) {
static const auto *flash_opacity =
(Hyprlang::FLOAT *const *)(getConfigValue(pHandle, "flash_opacity")
->getDataStaticPtr());
pWindow->m_fAlpha = **flash_opacity;
// pWindow->m_fAlpha = g_fFlashOpacity;
pWindow->m_fAlpha.setConfig(&m_sFocusInAnimConfig);
pWindow->m_fAlpha.setCallbackOnEnd([this, pWindow, pHandle](void *) {
*pWindow->m_alpha = **flash_opacity;
pWindow->m_alpha->setConfig(m_sFocusInAnimConfig);
pWindow->m_alpha->setCallbackOnEnd([this, pWindow, pHandle](CWeakPointer<CBaseAnimatedVariable> pAnim) {
static const auto *active_opacity =
(Hyprlang::FLOAT *const *)(HyprlandAPI::getConfigValue(
pHandle, "decoration:active_opacity")
->getDataStaticPtr());
// Make sure we restore to the active window opacity
pWindow->m_fAlpha = **active_opacity;
// pWindow->m_fAlpha = g_fActiveOpacity;
pWindow->m_fAlpha.setConfig(&m_sFocusOutAnimConfig);
*pWindow->m_alpha = **active_opacity;
pWindow->m_alpha->setConfig(m_sFocusOutAnimConfig);
});
}
32 changes: 16 additions & 16 deletions src/IFocusAnimation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@ void IFocusAnimation::init(HANDLE pHandle, std::string animationName) {
Hyprlang::FLOAT{5.f});

m_sFocusInAnimConfig =
*(g_pConfigManager->getAnimationPropertyConfig("global"));
m_sFocusInAnimConfig.internalEnabled = 1;
m_sFocusInAnimConfig.internalStyle =
(g_pConfigManager->getAnimationPropertyConfig("global"));
m_sFocusInAnimConfig->internalEnabled = 1;
m_sFocusInAnimConfig->internalStyle =
std::string("hyprfocus_") + animationName + std::string("_in");
m_sFocusInAnimConfig.pValues = &m_sFocusInAnimConfig;
m_sFocusInAnimConfig->pValues = m_sFocusInAnimConfig;

m_sFocusOutAnimConfig =
*(g_pConfigManager->getAnimationPropertyConfig("global"));
m_sFocusOutAnimConfig.internalEnabled = 1;
m_sFocusOutAnimConfig.internalStyle =
(g_pConfigManager->getAnimationPropertyConfig("global"));
m_sFocusOutAnimConfig->internalEnabled = 1;
m_sFocusOutAnimConfig->internalStyle =
std::string("hyprfocus_") + animationName + std::string("_out");
m_sFocusOutAnimConfig.pValues = &m_sFocusOutAnimConfig;
m_sFocusOutAnimConfig->pValues = CWeakPointer<SAnimationPropertyConfig>(m_sFocusOutAnimConfig);
}

void IFocusAnimation::setup(HANDLE pHandle, std::string animationName) {
Expand All @@ -55,17 +55,17 @@ void IFocusAnimation::onWindowFocus(PHLWINDOW pWindow, HANDLE pHandle) {
(Hyprlang::FLOAT *const *)(HyprlandAPI::getConfigValue(
pHandle, configPrefix() + "out_speed")
->getDataStaticPtr());
m_sFocusInAnimConfig.internalBezier = *inBezier;
m_sFocusInAnimConfig.internalSpeed = **inSpeed;
m_sFocusInAnimConfig->internalBezier = *inBezier;
m_sFocusInAnimConfig->internalSpeed = **inSpeed;

m_sFocusOutAnimConfig.internalBezier = *outBezier;
m_sFocusOutAnimConfig.internalSpeed = **outSpeed;
m_sFocusOutAnimConfig->internalBezier = *outBezier;
m_sFocusOutAnimConfig->internalSpeed = **outSpeed;

hyprfocus_log(LOG, "In bezier: {} In speed: {} Out bezier: {} Out speed: {}",
m_sFocusInAnimConfig.internalBezier,
m_sFocusInAnimConfig.internalSpeed,
m_sFocusOutAnimConfig.internalBezier,
m_sFocusOutAnimConfig.internalSpeed);
m_sFocusInAnimConfig->internalBezier,
m_sFocusInAnimConfig->internalSpeed,
m_sFocusOutAnimConfig->internalBezier,
m_sFocusOutAnimConfig->internalSpeed);
}

void IFocusAnimation::addConfigValue(HANDLE pHandle, std::string name,
Expand Down
7 changes: 5 additions & 2 deletions src/IFocusAnimation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

#include <hyprland/src/config/ConfigManager.hpp>

using namespace Hyprutils::Memory;
using namespace Hyprutils::Animation;

class IFocusAnimation {
public:
virtual void onWindowFocus(PHLWINDOW pWindow, HANDLE pHandle);
Expand All @@ -16,8 +19,8 @@ class IFocusAnimation {
Hyprlang::CConfigValue *getConfigValue(HANDLE pHandle, std::string name);

public:
SAnimationPropertyConfig m_sFocusInAnimConfig;
SAnimationPropertyConfig m_sFocusOutAnimConfig;
CSharedPointer<SAnimationPropertyConfig> m_sFocusInAnimConfig = makeShared<SAnimationPropertyConfig>();
CSharedPointer<SAnimationPropertyConfig> m_sFocusOutAnimConfig = makeShared<SAnimationPropertyConfig>();

std::string m_szAnimationName;

Expand Down
43 changes: 24 additions & 19 deletions src/Shrink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "Log.hpp"
#include <hyprland/src/Compositor.hpp>
#include <hyprland/src/desktop/Window.hpp>
#include <hyprland/src/managers/AnimationManager.hpp>
#include <hyprland/src/managers/animation/AnimationManager.hpp>
#include <hyprland/src/plugins/PluginAPI.hpp>

void CShrink::init(HANDLE pHandle, std::string animationName) {
Expand All @@ -22,39 +22,44 @@ void CShrink::setup(HANDLE pHandle, std::string animationName) {

void CShrink::onWindowFocus(PHLWINDOW pWindow, HANDLE pHandle) {
std::string currentAnimStyle =
pWindow->m_vRealSize.getConfig()->internalStyle;
pWindow->m_realSize->getConfig()->internalStyle;
hyprfocus_log(LOG, "Current animation style: {}", currentAnimStyle);
if ((currentAnimStyle == "popout" || currentAnimStyle == "popin") &&
pWindow->m_vRealSize.isBeingAnimated()) {
pWindow->m_realSize->isBeingAnimated()) {
hyprfocus_log(LOG, "Shrink: Window is already being animated, skipping");
return;
}

IFocusAnimation::onWindowFocus(pWindow, pHandle);

pWindow->m_vRealSize.setConfig(&m_sFocusOutAnimConfig);
pWindow->m_vRealPosition.setConfig(&m_sFocusOutAnimConfig);
pWindow->m_realSize->setConfig(m_sFocusOutAnimConfig);
pWindow->m_realPosition->setConfig(m_sFocusOutAnimConfig);

g_pAnimationManager->createAnimation(1.0f, m_sShrinkAnimation,
m_sFocusOutAnimConfig, pWindow, AVARDAMAGE_ENTIRE);

m_sShrinkAnimation.registerVar();
m_sShrinkAnimation.create(1.0f, &m_sFocusInAnimConfig, AVARDAMAGE_ENTIRE);
static const auto *shrinkPercentage =
(Hyprlang::FLOAT *const *)(getConfigValue(pHandle, "shrink_percentage")
->getDataStaticPtr());
hyprfocus_log(LOG, "Shrink percentage: {}", **shrinkPercentage);
m_sShrinkAnimation = **shrinkPercentage;
m_sShrinkAnimation->setValue(**shrinkPercentage);

m_sShrinkAnimation.setUpdateCallback([this, pWindow](void *pShrinkAnimation) {
const auto GOALPOS = pWindow->m_vRealPosition.goal();
const auto GOALSIZE = pWindow->m_vRealSize.goal();
m_sShrinkAnimation->setUpdateCallback(
[this, pWindow](CWeakPointer<CBaseAnimatedVariable> pShrinkAnimation) {
const auto GOALPOS = pWindow->m_realPosition->goal();
const auto GOALSIZE = pWindow->m_realSize->goal();

const auto *PANIMATION = (CAnimatedVariable<float> *)pShrinkAnimation;
const auto *PANIMATION =
(CAnimatedVariable<float> *)pShrinkAnimation.get();

pWindow->m_vRealSize.setValue(GOALSIZE * PANIMATION->value());
pWindow->m_vRealPosition.setValue(GOALPOS + GOALSIZE / 2.f -
pWindow->m_vRealSize.value() / 2.f);
});
pWindow->m_realSize->setValue(GOALSIZE * PANIMATION->value());
pWindow->m_realPosition->setValue(GOALPOS + GOALSIZE / 2.f -
pWindow->m_realSize->value() / 2.f);
});

m_sShrinkAnimation.setCallbackOnEnd([this, pWindow](void *pShrinkAnimation) {
((CAnimatedVariable<float> *)pShrinkAnimation)->resetAllCallbacks();
});
m_sShrinkAnimation->setCallbackOnEnd(
[this, pWindow](CWeakPointer<CBaseAnimatedVariable> pShrinkAnimation) {
((CAnimatedVariable<float> *)(pShrinkAnimation.get()))
->resetAllCallbacks();
});
}
2 changes: 1 addition & 1 deletion src/Shrink.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ class CShrink : public IFocusAnimation {
void init(HANDLE pHandle, std::string animationName) override;
void setup(HANDLE pHandle, std::string animationName) override;

CAnimatedVariable<float> m_sShrinkAnimation;
PHLANIMVAR<float> m_sShrinkAnimation;
};
28 changes: 20 additions & 8 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

#include <hyprland/src/Compositor.hpp>
#include <hyprland/src/desktop/Window.hpp>
#include <hyprland/src/managers/AnimationManager.hpp>
#include <hyprland/src/managers/animation/AnimationManager.hpp>

#include "Flash.hpp"
#include "Shrink.hpp"
Expand Down Expand Up @@ -64,23 +64,34 @@ void flashWindow(PHLWINDOW pWindow) {
}
}

void flashCurrentWindow(std::string) {
SDispatchResult flashCurrentWindow(std::string) {
hyprfocus_log(LOG, "Flashing current window");
SDispatchResult result = {
.passEvent = false,
.success = true,
};
static auto *const PHYPRFOCUSENABLED =
(Hyprlang::INT *const *)HyprlandAPI::getConfigValue(
PHANDLE, "plugin:hyprfocus:enabled")
->getDataStaticPtr();
if (!*PHYPRFOCUSENABLED) {
const std::string message = "HyprFocus is disabled";
hyprfocus_log(LOG, "HyprFocus is disabled");
return;
result.success = false;
result.error = message;
return result;
}

if (g_pPreviouslyFocusedWindow == nullptr) {
const std::string message = "No previously focused window";
hyprfocus_log(LOG, "No previously focused window");
return;
result.success = false;
result.error = message;
return result;
}

result.passEvent = true;
flashWindow(g_pPreviouslyFocusedWindow);
return result;
}

static void onActiveWindowChange(void *self, std::any data) {
Expand Down Expand Up @@ -117,7 +128,7 @@ static void onActiveWindowChange(void *self, std::any data) {
return;
}

if (PWINDOW->m_bIsFloating && !**PANIMATEFLOATING) {
if (PWINDOW->m_isFloating && !**PANIMATEFLOATING) {
hyprfocus_log(LOG, "Floating window, not animating");
g_pPreviouslyFocusedWindow = PWINDOW;
return;
Expand Down Expand Up @@ -169,7 +180,7 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
Hyprlang::INT{1});
HyprlandAPI::addConfigValue(PHANDLE, "plugin:hyprfocus:focus_animation",
Hyprlang::STRING("flash"));
HyprlandAPI::addDispatcher(PHANDLE, "animatefocused", &flashCurrentWindow);
HyprlandAPI::addDispatcherV2(PHANDLE, "animatefocused", &flashCurrentWindow);

g_mAnimations["flash"] = std::make_unique<CFlash>();
g_mAnimations["shrink"] = std::make_unique<CShrink>();
Expand All @@ -181,7 +192,8 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) {
}

HyprlandAPI::reloadConfig();
g_pConfigManager->tick();
// g_pConfigManager->tick();
g_pAnimationManager->tick();
hyprfocus_log(LOG, "Reloaded config");

// Register callbacks
Expand Down