mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-07 15:05:58 +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
|
- 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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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."); \
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
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
|
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);
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue