From bcf7ee6dc225c00b2aea9891ea42aeb18e5b0cc8 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Wed, 23 Mar 2022 22:01:59 +0100 Subject: [PATCH] Added basic animations for windows --- README.md | 3 +- src/Compositor.cpp | 3 ++ src/Compositor.hpp | 1 + src/config/ConfigManager.cpp | 6 ++++ src/events/Devices.cpp | 5 +-- src/events/Monitors.cpp | 14 ++++---- src/layout/DwindleLayout.cpp | 11 ++++--- src/managers/AnimationManager.cpp | 53 +++++++++++++++++++++++++++++++ src/managers/AnimationManager.hpp | 17 ++++++++++ src/render/Renderer.cpp | 19 +++++++++-- 10 files changed, 116 insertions(+), 16 deletions(-) create mode 100644 src/managers/AnimationManager.cpp create mode 100644 src/managers/AnimationManager.hpp diff --git a/README.md b/README.md index 33e5e5bc..288015ab 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Hyprland is in very early dev, expect bugs, instabilities and crashes. You have Nevertheless, REPORT any you find! Make an issue! # Key features + - Basic window animations - Config reloaded instantly upon saving - Easily expandable and readable codebase - Support for docks/whatever @@ -25,7 +26,7 @@ Nevertheless, REPORT any you find! Make an issue! - Moving/resizing windows # Major to-dos - - Animations + - Animations (better) - Rounded corners - Blur - Fadein/out diff --git a/src/Compositor.cpp b/src/Compositor.cpp index d7b7df4a..804f403c 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -126,6 +126,9 @@ void CCompositor::startCompositor() { Debug::log(LOG, "Creating the LayoutManager!"); g_pLayoutManager = std::make_unique(); + + Debug::log(LOG, "Creating the AnimationManager!"); + g_pAnimationManager = std::make_unique(); // // diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 748b894f..6f1c9ed6 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -13,6 +13,7 @@ #include "managers/InputManager.hpp" #include "managers/LayoutManager.hpp" #include "managers/KeybindManager.hpp" +#include "managers/AnimationManager.hpp" #include "helpers/Monitor.hpp" #include "helpers/Workspace.hpp" #include "Window.hpp" diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index b4a218f0..2a481ed2 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -21,6 +21,12 @@ CConfigManager::CConfigManager() { configValues["general:gaps_out"].intValue = 20; configValues["general:col.active_border"].intValue = 0xffffffff; configValues["general:col.inactive_border"].intValue = 0xff444444; + + configValues["animations:enabled"].intValue = 1; + configValues["animations:speed"].floatValue = 7.f; + configValues["animations:windows"].intValue = 1; + configValues["animations:borders"].intValue = 1; + configValues["animations:fadein"].intValue = 1; } void CConfigManager::init() { diff --git a/src/events/Devices.cpp b/src/events/Devices.cpp index 846b9070..ab259f43 100644 --- a/src/events/Devices.cpp +++ b/src/events/Devices.cpp @@ -57,8 +57,9 @@ void Events::listener_mouseAxis(wl_listener* listener, void* data) { void Events::listener_requestMouse(wl_listener* listener, void* data) { const auto EVENT = (wlr_seat_pointer_request_set_cursor_event*)data; - if (EVENT->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) - wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, EVENT->surface, EVENT->hotspot_x, EVENT->hotspot_y); + // TODO: crashes sometimes + //if (EVENT->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) + // wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, EVENT->surface, EVENT->hotspot_x, EVENT->hotspot_y); } void Events::listener_newInput(wl_listener* listener, void* data) { diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 072f5c8a..70b4cee4 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -98,6 +98,14 @@ void Events::listener_newOutput(wl_listener* listener, void* data) { void Events::listener_monitorFrame(wl_listener* listener, void* data) { SMonitor* const PMONITOR = wl_container_of(listener, PMONITOR, listen_monitorFrame); + // Hack: only check when monitor number 1 refreshes, saves a bit of resources. + // This is for stuff that should be run every frame + // TODO: do this on the most Hz monitor + if (PMONITOR->ID == 0) { + g_pCompositor->sanityCheckWorkspaces(); + g_pAnimationManager->tick(); + } + timespec now; clock_gettime(CLOCK_MONOTONIC, &now); const float bgcol[4] = {0.1f, 0.1f, 0.1f, 1.f}; @@ -115,12 +123,6 @@ void Events::listener_monitorFrame(wl_listener* listener, void* data) { wlr_renderer_end(g_pCompositor->m_sWLRRenderer); wlr_output_commit(PMONITOR->output); - - // Sanity check the workspaces. - // Hack: only check when monitor number 1 refreshes, saves a bit of resources. - if (PMONITOR->ID == 0) { - g_pCompositor->sanityCheckWorkspaces(); - } } void Events::listener_monitorDestroy(wl_listener* listener, void* data) { diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 3c1ee742..758a938d 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -109,10 +109,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) { PWINDOW->m_vEffectivePosition = PWINDOW->m_vEffectivePosition + OFFSETTOPLEFT; PWINDOW->m_vEffectiveSize = PWINDOW->m_vEffectiveSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT; - // TEMP: remove when anims added - PWINDOW->m_vRealPosition = PWINDOW->m_vEffectivePosition; - PWINDOW->m_vRealSize = PWINDOW->m_vEffectiveSize; - g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize); + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vEffectiveSize); } void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) { @@ -145,6 +142,9 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) { applyNodeDataToWindow(PNODE); + pWindow->m_vRealPosition = PNODE->position + PNODE->size / 2.f; + pWindow->m_vRealSize = Vector2D(5, 5); + return; } @@ -193,6 +193,9 @@ void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) { applyNodeDataToWindow(PNODE); applyNodeDataToWindow(OPENINGON); + + pWindow->m_vRealPosition = PNODE->position + PNODE->size / 2.f; + pWindow->m_vRealSize = Vector2D(5,5); } void CHyprDwindleLayout::onWindowRemoved(CWindow* pWindow) { diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp new file mode 100644 index 00000000..99176488 --- /dev/null +++ b/src/managers/AnimationManager.cpp @@ -0,0 +1,53 @@ +#include "AnimationManager.hpp" +#include "../Compositor.hpp" + +void CAnimationManager::tick() { + + bool animationsDisabled = false; + + if (!g_pConfigManager->getInt("animations:enabled")) + animationsDisabled = true; + + const bool WINDOWSENABLED = g_pConfigManager->getInt("animations:windows"); + const bool BORDERSENABLED = g_pConfigManager->getInt("animations:borders"); + const bool FADEENABLED = g_pConfigManager->getInt("animations:fadein"); + const float ANIMSPEED = g_pConfigManager->getFloat("animations:speed"); + + for (auto& w : g_pCompositor->m_lWindows) { + if (animationsDisabled) { + w.m_vRealPosition = w.m_vEffectivePosition; + w.m_vRealSize = w.m_vEffectiveSize; + continue; + } + + // process the window + if (WINDOWSENABLED) { + if (deltazero(w.m_vRealPosition, w.m_vEffectivePosition) && deltazero(w.m_vRealSize, w.m_vEffectiveSize)) { + continue; + } + + if (deltaSmallToFlip(w.m_vRealPosition, w.m_vEffectivePosition) || deltaSmallToFlip(w.m_vRealSize, w.m_vEffectiveSize)) { + w.m_vRealPosition = w.m_vEffectivePosition; + w.m_vRealSize = w.m_vEffectiveSize; + g_pXWaylandManager->setWindowSize(&w, w.m_vRealSize); + continue; + } + + // if it is to be animated, animate it. + w.m_vRealPosition = Vector2D(parabolic(w.m_vRealPosition.x, w.m_vEffectivePosition.x, ANIMSPEED), parabolic(w.m_vRealPosition.y, w.m_vEffectivePosition.y, ANIMSPEED)); + w.m_vRealSize = Vector2D(parabolic(w.m_vRealSize.x, w.m_vEffectiveSize.x, ANIMSPEED), parabolic(w.m_vRealSize.y, w.m_vEffectiveSize.y, ANIMSPEED)); + } + } +} + +bool CAnimationManager::deltaSmallToFlip(const Vector2D& a, const Vector2D& b) { + return std::abs(a.x - b.x) < 0.5f && std::abs(a.y - b.y) < 0.5f; +} + +bool CAnimationManager::deltazero(const Vector2D& a, const Vector2D& b) { + return a.x == b.x && a.y == b.y; +} + +double CAnimationManager::parabolic(double from, double to, double incline) { + return from + ((to - from) / incline); +} \ No newline at end of file diff --git a/src/managers/AnimationManager.hpp b/src/managers/AnimationManager.hpp new file mode 100644 index 00000000..38e433c6 --- /dev/null +++ b/src/managers/AnimationManager.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "../defines.hpp" +#include + +class CAnimationManager { +public: + + void tick(); + +private: + bool deltaSmallToFlip(const Vector2D& a, const Vector2D& b); + bool deltazero(const Vector2D& a, const Vector2D& b); + double parabolic(double, double, double); +}; + +inline std::unique_ptr g_pAnimationManager; \ No newline at end of file diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 530aa0a9..ff141b68 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -18,7 +18,14 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { double outputX = 0, outputY = 0; wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, RDATA->output, &outputX, &outputY); - wlr_box windowBox = {outputX + RDATA->x + x, outputY + RDATA->y + y, surface->current.width, surface->current.height}; + + wlr_box windowBox; + // if (RDATA->surface) { + // windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, RDATA->w, RDATA->h}; + // wlr_renderer_scissor(g_pCompositor->m_sWLRRenderer, &windowBox); + // } else { + windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, surface->current.width, surface->current.height}; + // } scaleBox(&windowBox, RDATA->output->scale); const auto TRANSFORM = wlr_output_transform_invert(surface->current.transform); @@ -30,6 +37,8 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { wlr_surface_send_frame_done(surface, RDATA->when); wlr_presentation_surface_sampled_on_output(g_pCompositor->m_sWLRPresentation, surface, RDATA->output); + + wlr_renderer_scissor(g_pCompositor->m_sWLRRenderer, nullptr); } bool shouldRenderWindow(CWindow* pWindow, SMonitor* pMonitor) { @@ -64,7 +73,11 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec* if (decorate && !pWindow->m_bX11DoesntWantBorders) drawBorderForWindow(pWindow, pMonitor); - SRenderData renderdata = {pMonitor->output, time, pWindow->m_vRealPosition.x, pWindow->m_vRealPosition.y}; + const auto REALPOS = pWindow->m_vRealPosition; + SRenderData renderdata = {pMonitor->output, time, REALPOS.x, REALPOS.y}; + renderdata.surface = g_pXWaylandManager->getWindowSurface(pWindow); + renderdata.w = pWindow->m_vRealSize.x; + renderdata.h = pWindow->m_vRealSize.y; wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata); @@ -373,7 +386,7 @@ void CHyprRenderer::drawBorderForWindow(CWindow* pWindow, SMonitor* pMonitor) { Vector2D correctPos = pWindow->m_vRealPosition - pMonitor->vecPosition; // top - wlr_box border = {correctPos.x - BORDERSIZE, correctPos.y - BORDERSIZE, pWindow->m_vRealSize.x + 2 * BORDERSIZE, BORDERSIZE }; + wlr_box border = {correctPos.x - BORDERSIZE, correctPos.y - BORDERSIZE, pWindow->m_vRealSize.x + 2 * BORDERSIZE, BORDERSIZE}; wlr_render_rect(g_pCompositor->m_sWLRRenderer, &border, BORDERWLRCOL, pMonitor->output->transform_matrix); // bottom