mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-22 19:05:59 +01:00
fadeout done 🎉
This commit is contained in:
parent
f8e0b0b448
commit
a49bbf4508
12 changed files with 176 additions and 8 deletions
|
@ -23,6 +23,7 @@ Nevertheless, REPORT any you find! Make an issue!
|
|||
- Config reloaded instantly upon saving
|
||||
- Easily expandable and readable codebase
|
||||
- Rounded corners
|
||||
- Fade in/out
|
||||
- Support for docks/whatever
|
||||
- Window rules
|
||||
- Monitor rules
|
||||
|
@ -33,10 +34,8 @@ Nevertheless, REPORT any you find! Make an issue!
|
|||
# Major to-dos
|
||||
- Damage tracking
|
||||
- Animations (better)
|
||||
- Fix XWayland focus
|
||||
- Fix GDK popups on multimon
|
||||
- Blur
|
||||
- Fadein/out
|
||||
- Fix electron rendering issues
|
||||
- Optimization
|
||||
- Fix weird scroll on XWayland
|
||||
|
|
|
@ -26,13 +26,19 @@ general {
|
|||
col.inactive_border=0x66333333
|
||||
}
|
||||
|
||||
decoration {
|
||||
rounding=10
|
||||
}
|
||||
|
||||
animations {
|
||||
enabled=1
|
||||
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=1
|
||||
borders=1
|
||||
fadein=1 # not yet implemented
|
||||
borders_speed=20
|
||||
fadein=1 # fade in AND out
|
||||
fadein_speed=20
|
||||
}
|
||||
|
||||
dwindle {
|
||||
|
|
|
@ -559,6 +559,8 @@ void CCompositor::cleanupWindows() {
|
|||
if (!w->m_bFadingOut || w->m_fAlpha == 0.f) {
|
||||
m_lWindows.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");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
#ifndef __INTELLISENSE__
|
||||
#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()); \
|
||||
RIP("Assertion failed! See the log in /tmp/hypr/hyprland.log for more info."); \
|
||||
}
|
||||
|
|
|
@ -171,6 +171,9 @@ void Events::listener_unmapWindow(void* owner, void* data) {
|
|||
g_pCompositor->m_pLastFocus = nullptr;
|
||||
}
|
||||
|
||||
// Allow the renderer to catch the last frame.
|
||||
g_pHyprOpenGL->makeWindowSnapshot(PWINDOW);
|
||||
|
||||
PWINDOW->m_bMappedX11 = false;
|
||||
|
||||
// remove the fullscreen window status from workspace if we closed it
|
||||
|
|
|
@ -261,8 +261,8 @@ void CHyprDwindleLayout::onWindowRemoved(CWindow* pWindow) {
|
|||
m_lDwindleNodesData.remove(*PNODE);
|
||||
|
||||
// jump back like it jumps in
|
||||
pWindow->m_vEffectivePosition = pWindow->m_vEffectivePosition + ((pWindow->m_vEffectiveSize - Vector2D(5, 5)) * 0.5f);
|
||||
pWindow->m_vEffectiveSize = Vector2D(5, 5);
|
||||
//pWindow->m_vEffectivePosition = pWindow->m_vEffectivePosition + ((pWindow->m_vEffectiveSize - Vector2D(5, 5)) * 0.5f);
|
||||
// pWindow->m_vEffectiveSize = Vector2D(5, 5);
|
||||
}
|
||||
|
||||
void CHyprDwindleLayout::recalculateMonitor(const int& monid) {
|
||||
|
|
62
src/render/Framebuffer.cpp
Normal file
62
src/render/Framebuffer.cpp
Normal 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;
|
||||
}
|
22
src/render/Framebuffer.hpp
Normal file
22
src/render/Framebuffer.hpp
Normal 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
|
||||
};
|
|
@ -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
|
||||
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_iCurrentOutputFb);
|
||||
}
|
||||
|
||||
void CHyprOpenGLImpl::end() {
|
||||
|
@ -324,3 +326,57 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CColor& col, int thick, i
|
|||
|
||||
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);
|
||||
}
|
|
@ -5,10 +5,12 @@
|
|||
#include "../helpers/Color.hpp"
|
||||
#include <wlr/render/egl.h>
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "Shaders.hpp"
|
||||
#include "Shader.hpp"
|
||||
#include "Texture.hpp"
|
||||
#include "Framebuffer.hpp"
|
||||
|
||||
inline const float matrixFlip180[] = {
|
||||
1.0f, 0.0f, 0.0f,
|
||||
|
@ -40,11 +42,18 @@ public:
|
|||
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 makeWindowSnapshot(CWindow*);
|
||||
void renderSnapshot(CWindow**);
|
||||
|
||||
void clear(const CColor&);
|
||||
void scissor(const wlr_box*);
|
||||
|
||||
SCurrentRenderData m_RenderData;
|
||||
|
||||
GLint m_iCurrentOutputFb = 0;
|
||||
|
||||
std::unordered_map<CWindow*, CFramebuffer> m_mWindowFramebuffers;
|
||||
|
||||
private:
|
||||
std::list<GLuint> m_lBuffers;
|
||||
std::list<GLuint> m_lTextures;
|
||||
|
|
|
@ -82,6 +82,11 @@ void CHyprRenderer::renderWorkspaceWithFullscreenWindow(SMonitor* pMonitor, SWor
|
|||
}
|
||||
|
||||
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;
|
||||
SRenderData renderdata = {pMonitor->output, time, REALPOS.x, REALPOS.y};
|
||||
renderdata.surface = g_pXWaylandManager->getWindowSurface(pWindow);
|
||||
|
@ -134,7 +139,7 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
|
|||
|
||||
// Non-floating
|
||||
for (auto& w : g_pCompositor->m_lWindows) {
|
||||
if (!g_pCompositor->windowValidMapped(&w))
|
||||
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
|
||||
continue;
|
||||
|
||||
if (w.m_bIsFloating)
|
||||
|
@ -149,7 +154,7 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
|
|||
|
||||
// floating on top
|
||||
for (auto& w : g_pCompositor->m_lWindows) {
|
||||
if (!g_pCompositor->windowValidMapped(&w))
|
||||
if (!g_pCompositor->windowValidMapped(&w) && !w.m_bFadingOut)
|
||||
continue;
|
||||
|
||||
if (!w.m_bIsFloating)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "../helpers/Monitor.hpp"
|
||||
#include "../helpers/Workspace.hpp"
|
||||
#include "../Window.hpp"
|
||||
#include "OpenGL.hpp"
|
||||
|
||||
class CHyprRenderer {
|
||||
public:
|
||||
|
@ -20,6 +21,9 @@ private:
|
|||
void renderWorkspaceWithFullscreenWindow(SMonitor*, SWorkspace*, timespec*);
|
||||
void renderWindow(CWindow*, SMonitor*, timespec*, bool);
|
||||
void renderDragIcon(SMonitor*, timespec*);
|
||||
|
||||
|
||||
friend class CHyprOpenGLImpl;
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CHyprRenderer> g_pHyprRenderer;
|
||||
|
|
Loading…
Reference in a new issue