fadeout done 🎉

This commit is contained in:
vaxerski 2022-04-05 20:49:15 +02:00
parent f8e0b0b448
commit a49bbf4508
12 changed files with 176 additions and 8 deletions

View file

@ -23,6 +23,7 @@ Nevertheless, REPORT any you find! Make an issue!
- Config reloaded instantly upon saving - Config reloaded instantly upon saving
- Easily expandable and readable codebase - Easily expandable and readable codebase
- Rounded corners - Rounded corners
- Fade in/out
- Support for docks/whatever - Support for docks/whatever
- Window rules - Window rules
- Monitor rules - Monitor rules
@ -33,10 +34,8 @@ Nevertheless, REPORT any you find! Make an issue!
# Major to-dos # Major to-dos
- Damage tracking - Damage tracking
- Animations (better) - Animations (better)
- Fix XWayland focus
- Fix GDK popups on multimon - Fix GDK popups on multimon
- Blur - Blur
- Fadein/out
- Fix electron rendering issues - Fix electron rendering issues
- Optimization - Optimization
- Fix weird scroll on XWayland - Fix weird scroll on XWayland

View file

@ -26,13 +26,19 @@ general {
col.inactive_border=0x66333333 col.inactive_border=0x66333333
} }
decoration {
rounding=10
}
animations { animations {
enabled=1 enabled=1
speed=7 speed=7
windows_speed=6 # specific speeds for components can be made with name_speed=float. 0 means use global (speed=float). If not set, will use the global value. windows_speed=6 # specific speeds for components can be made with name_speed=float. 0 means use global (speed=float). If not set, will use the global value.
windows=1 windows=1
borders=1 borders=1
fadein=1 # not yet implemented borders_speed=20
fadein=1 # fade in AND out
fadein_speed=20
} }
dwindle { dwindle {

View file

@ -559,6 +559,8 @@ void CCompositor::cleanupWindows() {
if (!w->m_bFadingOut || w->m_fAlpha == 0.f) { if (!w->m_bFadingOut || w->m_fAlpha == 0.f) {
m_lWindows.remove(*w); m_lWindows.remove(*w);
m_lWindowsFadingOut.remove(w); m_lWindowsFadingOut.remove(w);
g_pHyprOpenGL->m_mWindowFramebuffers[w].release();
g_pHyprOpenGL->m_mWindowFramebuffers.erase(w);
Debug::log(LOG, "Cleanup: cleaned up a window"); Debug::log(LOG, "Cleanup: cleaned up a window");
return; return;
} }

View file

@ -32,7 +32,7 @@
#ifndef __INTELLISENSE__ #ifndef __INTELLISENSE__
#define RASSERT(expr, reason, ...) \ #define RASSERT(expr, reason, ...) \
if (!expr) { \ if (!(expr)) { \
Debug::log(CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n%s\n\nat: line %d in %s", getFormat(reason, ##__VA_ARGS__).c_str(), __LINE__, ([]() constexpr->std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })().c_str()); \ Debug::log(CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n%s\n\nat: line %d in %s", getFormat(reason, ##__VA_ARGS__).c_str(), __LINE__, ([]() constexpr->std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })().c_str()); \
RIP("Assertion failed! See the log in /tmp/hypr/hyprland.log for more info."); \ RIP("Assertion failed! See the log in /tmp/hypr/hyprland.log for more info."); \
} }

View file

@ -171,6 +171,9 @@ void Events::listener_unmapWindow(void* owner, void* data) {
g_pCompositor->m_pLastFocus = nullptr; g_pCompositor->m_pLastFocus = nullptr;
} }
// Allow the renderer to catch the last frame.
g_pHyprOpenGL->makeWindowSnapshot(PWINDOW);
PWINDOW->m_bMappedX11 = false; PWINDOW->m_bMappedX11 = false;
// remove the fullscreen window status from workspace if we closed it // remove the fullscreen window status from workspace if we closed it

View file

@ -261,8 +261,8 @@ void CHyprDwindleLayout::onWindowRemoved(CWindow* pWindow) {
m_lDwindleNodesData.remove(*PNODE); m_lDwindleNodesData.remove(*PNODE);
// jump back like it jumps in // jump back like it jumps in
pWindow->m_vEffectivePosition = pWindow->m_vEffectivePosition + ((pWindow->m_vEffectiveSize - Vector2D(5, 5)) * 0.5f); //pWindow->m_vEffectivePosition = pWindow->m_vEffectivePosition + ((pWindow->m_vEffectiveSize - Vector2D(5, 5)) * 0.5f);
pWindow->m_vEffectiveSize = Vector2D(5, 5); // pWindow->m_vEffectiveSize = Vector2D(5, 5);
} }
void CHyprDwindleLayout::recalculateMonitor(const int& monid) { void CHyprDwindleLayout::recalculateMonitor(const int& monid) {

View file

@ -0,0 +1,62 @@
#include "Framebuffer.hpp"
#include "OpenGL.hpp"
bool CFramebuffer::alloc(int w, int h) {
bool firstAlloc = false;
if (m_iFb == (uint32_t)-1)
{
firstAlloc = true;
glGenFramebuffers(1, &m_iFb);
}
if (m_cTex.m_iTexID == 0)
{
firstAlloc = true;
glGenTextures(1, &m_cTex.m_iTexID);
glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
if (firstAlloc)
{
glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindFramebuffer(GL_FRAMEBUFFER, m_iFb);
glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_cTex.m_iTexID, 0);
auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
RASSERT((status == GL_FRAMEBUFFER_COMPLETE), "Framebuffer incomplete, couldn't create! (FB status: %i)", status);
Debug::log(LOG, "Framebuffer created, status %i", status);
}
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_iCurrentOutputFb);
m_Size = Vector2D(w, h);
return true;
}
void CFramebuffer::bind() {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_iFb);
glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.y);
}
void CFramebuffer::release() {
if (m_iFb != (uint32_t)-1 && m_iFb) {
glDeleteFramebuffers(1, &m_iFb);
}
if (m_cTex.m_iTexID) {
glDeleteTextures(1, &m_cTex.m_iTexID);
}
m_cTex.m_iTexID = 0;
m_iFb = -1;
}

View file

@ -0,0 +1,22 @@
#pragma once
#include "../defines.hpp"
#include "Texture.hpp"
class CFramebuffer {
public:
bool alloc(int w, int h);
void bind();
void release();
void reset();
Vector2D m_Position;
Vector2D m_Size;
float m_fScale = 1;
CTexture m_cTex;
GLuint m_iFb = -1;
wl_output_transform m_tTransform; // for saving state
};

View file

@ -106,6 +106,8 @@ void CHyprOpenGLImpl::begin(SMonitor* pMonitor) {
wlr_matrix_projection(m_RenderData.projection, pMonitor->vecSize.x, pMonitor->vecSize.y, WL_OUTPUT_TRANSFORM_NORMAL); // TODO: this is deprecated wlr_matrix_projection(m_RenderData.projection, pMonitor->vecSize.x, pMonitor->vecSize.y, WL_OUTPUT_TRANSFORM_NORMAL); // TODO: this is deprecated
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_iCurrentOutputFb);
} }
void CHyprOpenGLImpl::end() { void CHyprOpenGLImpl::end() {
@ -324,3 +326,57 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int thick, i
glDisableVertexAttribArray(m_shQUAD.posAttrib); glDisableVertexAttribArray(m_shQUAD.posAttrib);
} }
void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) {
// we trust the window is valid.
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
wlr_output_attach_render(PMONITOR->output, nullptr);
begin(PMONITOR);
const auto PFRAMEBUFFER = &m_mWindowFramebuffers[pWindow];
PFRAMEBUFFER->m_tTransform = g_pXWaylandManager->getWindowSurface(pWindow)->current.transform;
PFRAMEBUFFER->alloc(PMONITOR->vecSize.x, PMONITOR->vecSize.y);
PFRAMEBUFFER->bind();
clear(CColor(0,0,0,0)); // JIC
timespec now;
clock_gettime(CLOCK_MONOTONIC, &now);
g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders);
// restore original fb
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_iCurrentOutputFb);
glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecSize.y);
end();
wlr_output_rollback(PMONITOR->output);
}
void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) {
const auto PWINDOW = *pWindow;
auto it = m_mWindowFramebuffers.begin();
for (;it != m_mWindowFramebuffers.end(); it++) {
if (it->first == PWINDOW) {
break;
}
}
if (it == m_mWindowFramebuffers.end() || !it->second.m_cTex.m_iTexID)
return;
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
const auto TRANSFORM = wlr_output_transform_invert(it->second.m_tTransform);
float matrix[9];
wlr_box windowBox = {0, 0, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
wlr_matrix_project_box(matrix, &windowBox, TRANSFORM, 0, PMONITOR->output->transform_matrix);
renderTexture(it->second.m_cTex, matrix, PWINDOW->m_fAlpha, 0);
}

View file

@ -5,10 +5,12 @@
#include "../helpers/Color.hpp" #include "../helpers/Color.hpp"
#include <wlr/render/egl.h> #include <wlr/render/egl.h>
#include <list> #include <list>
#include <unordered_map>
#include "Shaders.hpp" #include "Shaders.hpp"
#include "Shader.hpp" #include "Shader.hpp"
#include "Texture.hpp" #include "Texture.hpp"
#include "Framebuffer.hpp"
inline const float matrixFlip180[] = { inline const float matrixFlip180[] = {
1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
@ -40,11 +42,18 @@ public:
void renderTexture(const CTexture&, float matrix[9], float a, int round = 0); void renderTexture(const CTexture&, float matrix[9], float a, int round = 0);
void renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0); void renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0);
void makeWindowSnapshot(CWindow*);
void renderSnapshot(CWindow**);
void clear(const CColor&); void clear(const CColor&);
void scissor(const wlr_box*); void scissor(const wlr_box*);
SCurrentRenderData m_RenderData; SCurrentRenderData m_RenderData;
GLint m_iCurrentOutputFb = 0;
std::unordered_map<CWindow*, CFramebuffer> m_mWindowFramebuffers;
private: private:
std::list<GLuint> m_lBuffers; std::list<GLuint> m_lBuffers;
std::list<GLuint> m_lTextures; std::list<GLuint> m_lTextures;

View file

@ -82,6 +82,11 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, SWor
} }
void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec* time, bool decorate) { void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec* time, bool decorate) {
if (pWindow->m_bFadingOut) {
g_pHyprOpenGL->renderSnapshot(&pWindow);
return;
}
const auto REALPOS = pWindow->m_vRealPosition; const auto REALPOS = pWindow->m_vRealPosition;
SRenderData renderdata = {pMonitor->output, time, REALPOS.x, REALPOS.y}; SRenderData renderdata = {pMonitor->output, time, REALPOS.x, REALPOS.y};
renderdata.surface = g_pXWaylandManager->getWindowSurface(pWindow); renderdata.surface = g_pXWaylandManager->getWindowSurface(pWindow);
@ -134,7 +139,7 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
// Non-floating // Non-floating
for (auto& w : g_pCompositor->m_lWindows) { for (auto& w : g_pCompositor->m_lWindows) {
if (!g_pCompositor->windowValidMapped(&w)) if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
continue; continue;
if (w.m_bIsFloating) if (w.m_bIsFloating)
@ -149,7 +154,7 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
// floating on top // floating on top
for (auto& w : g_pCompositor->m_lWindows) { for (auto& w : g_pCompositor->m_lWindows) {
if (!g_pCompositor->windowValidMapped(&w)) if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
continue; continue;
if (!w.m_bIsFloating) if (!w.m_bIsFloating)

View file

@ -5,6 +5,7 @@
#include "../helpers/Monitor.hpp" #include "../helpers/Monitor.hpp"
#include "../helpers/Workspace.hpp" #include "../helpers/Workspace.hpp"
#include "../Window.hpp" #include "../Window.hpp"
#include "OpenGL.hpp"
class CHyprRenderer { class CHyprRenderer {
public: public:
@ -20,6 +21,9 @@ private:
void renderWorkspaceWithFullscreenWindow(SMonitor*, SWorkspace*, timespec*); void renderWorkspaceWithFullscreenWindow(SMonitor*, SWorkspace*, timespec*);
void renderWindow(CWindow*, SMonitor*, timespec*, bool); void renderWindow(CWindow*, SMonitor*, timespec*, bool);
void renderDragIcon(SMonitor*, timespec*); void renderDragIcon(SMonitor*, timespec*);
friend class CHyprOpenGLImpl;
}; };
inline std::unique_ptr<CHyprRenderer> g_pHyprRenderer; inline std::unique_ptr<CHyprRenderer> g_pHyprRenderer;