From 770bada5d541e737ae17744f70eb019494471a29 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Wed, 22 Jun 2022 15:45:56 +0200 Subject: [PATCH] Fixed oversized apps' incorrect layout --- src/Compositor.cpp | 9 ++++++- src/config/ConfigManager.cpp | 1 + src/events/Windows.cpp | 8 ++++++ src/managers/XWaylandManager.cpp | 10 ++------ src/managers/input/InputManager.cpp | 8 ++++++ src/render/OpenGL.cpp | 40 +++++++++++++++++++++-------- src/render/OpenGL.hpp | 8 ++++-- src/render/Renderer.cpp | 28 +++++++++++++++++++- 8 files changed, 90 insertions(+), 22 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 32ffab34..a5339948 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -443,7 +443,11 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pW double subx, suby; - const auto PFOUND = wlr_xdg_surface_surface_at(PSURFACE, pos.x - pWindow->m_vRealPosition.vec().x, pos.y - pWindow->m_vRealPosition.vec().y, &subx, &suby); + // calc for oversized windows... fucking bullshit, again. + wlr_box geom; + wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom); + + const auto PFOUND = wlr_xdg_surface_surface_at(PSURFACE, pos.x - pWindow->m_vRealPosition.vec().x + geom.x, pos.y - pWindow->m_vRealPosition.vec().y + geom.y, &subx, &suby); if (PFOUND) { sl.x = subx; @@ -454,6 +458,9 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pW sl.x = pos.x - pWindow->m_vRealPosition.vec().x; sl.y = pos.y - pWindow->m_vRealPosition.vec().y; + sl.x += geom.x; + sl.y += geom.y; + return PSURFACE->surface; } diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index aba0b1ff..d95f5a05 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -47,6 +47,7 @@ void CConfigManager::setDefaultVars() { configValues["decoration:inactive_opacity"].floatValue = 1; configValues["decoration:fullscreen_opacity"].floatValue = 1; configValues["decoration:multisample_edges"].intValue = 0; + configValues["decoration:no_blur_on_oversized"].intValue = 1; configValues["dwindle:pseudotile"].intValue = 0; configValues["dwindle:col.group_border"].intValue = 0x66777700; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index b84b9d2d..48571892 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -19,6 +19,14 @@ void addViewCoords(void* pWindow, int* x, int* y) { const auto PWINDOW = (CWindow*)pWindow; *x += PWINDOW->m_vRealPosition.goalv().x; *y += PWINDOW->m_vRealPosition.goalv().y; + + if (!PWINDOW->m_bIsX11) { + wlr_box geom; + wlr_xdg_surface_get_geometry(PWINDOW->m_uSurface.xdg, &geom); + + *x -= geom.x; + *y -= geom.y; + } } void Events::listener_mapWindow(void* owner, void* data) { diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 5927274e..65f5ddd8 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -124,14 +124,8 @@ void CHyprXWaylandManager::sendCloseWindow(CWindow* pWindow) { void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, const Vector2D& size) { if (pWindow->m_bIsX11) wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pWindow->m_vRealPosition.vec().x, pWindow->m_vRealPosition.vec().y, size.x, size.y); - else { - // I don't know if this is fucking correct, but the fucking idea of putting shadows into a window's surface is borderline criminal. - - const auto XDELTA = pWindow->m_uSurface.xdg->current.geometry.width && pWindow->m_uSurface.xdg->current.geometry.height ? pWindow->m_uSurface.xdg->surface->current.width - pWindow->m_uSurface.xdg->current.geometry.width : 0; - const auto YDELTA = pWindow->m_uSurface.xdg->current.geometry.width && pWindow->m_uSurface.xdg->current.geometry.height ? pWindow->m_uSurface.xdg->surface->current.height - pWindow->m_uSurface.xdg->current.geometry.height : 0; - - wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x - XDELTA, size.y - YDELTA); - } + else + wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y); } void CHyprXWaylandManager::setWindowStyleTiled(CWindow* pWindow, uint32_t edgez) { diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 63e2d970..6bc59472 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -172,6 +172,14 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { Vector2D surfaceLocal = surfacePos == Vector2D(-1337, -1337) ? surfaceCoords : mouseCoords - surfacePos; + if (pFoundWindow && !pFoundWindow->m_bIsX11 && surfacePos != Vector2D(-1337, -1337)) { + // calc for oversized windows... fucking bullshit. + wlr_box geom; + wlr_xdg_surface_get_geometry(pFoundWindow->m_uSurface.xdg, &geom); + + surfaceLocal = mouseCoords - surfacePos + Vector2D(geom.x, geom.y); + } + if (pFoundWindow) { static auto *const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; if (*PFOLLOWMOUSE != 1 && !refocus) { diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index d8f64e0c..c503cb64 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -303,15 +303,15 @@ void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha renderTexture(CTexture(tex), pBox, alpha, round); } -void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool border) { +void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardopaque, bool border, bool allowPrimary) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); - renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, border); + renderTextureInternalWithDamage(tex, pBox, alpha, m_RenderData.pDamage, round, discardopaque, border, false, allowPrimary); scissor((wlr_box*)nullptr); } -void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool border, bool noAA) { +void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, pixman_region32_t* damage, int round, bool discardOpaque, bool border, bool noAA, bool allowPrimary) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!"); @@ -358,6 +358,8 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b // hacky fix to fix broken borders. // TODO: this is kinda slow... question mark? renderRect(pBox, CColor(0, 0, 0, 0), round); + + glDisable(GL_STENCIL_TEST); } glActiveTexture(GL_TEXTURE0); @@ -388,7 +390,19 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b glUniform1i(glGetUniformLocation(shader->program, "primitiveMultisample"), (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !border && !noAA)); glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); - glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); + + if (allowPrimary && m_RenderData.renderingPrimarySurface && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1)) { + const float verts[] = { + m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVTopLeft.y, // top right + m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVTopLeft.y, // top left + m_RenderData.primarySurfaceUVBottomRight.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom right + m_RenderData.primarySurfaceUVTopLeft.x, m_RenderData.primarySurfaceUVBottomRight.y, // bottom left + }; + + glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, verts); + } else { + glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); + } glEnableVertexAttribArray(shader->posAttrib); glEnableVertexAttribArray(shader->texAttrib); @@ -402,6 +416,8 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b } if (border) { + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_EQUAL, 1, -1); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); } @@ -548,9 +564,10 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!"); static auto *const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue; + static auto* const PNOBLUROVERSIZED = &g_pConfigManager->getConfigValuePtr("decoration:no_blur_on_oversized")->intValue; - if (*PBLURENABLED == 0) { - renderTexture(tex, pBox, a, round, false, border); + if (*PBLURENABLED == 0 || (*PNOBLUROVERSIZED && m_RenderData.primarySurfaceUVTopLeft != Vector2D(-1, -1))) { + renderTexture(tex, pBox, a, round, false, border, true); return; } @@ -607,13 +624,18 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, if (pixman_region32_not_empty(&damage)) { // render our great blurred FB static auto *const PBLURIGNOREOPACITY = &g_pConfigManager->getConfigValuePtr("decoration:blur_ignore_opacity")->intValue; - renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 255.f : a, &damage); + renderTextureInternalWithDamage(POUTFB->m_cTex, &MONITORBOX, *PBLURIGNOREOPACITY ? 255.f : a, &damage, 0, false, false, false, true); // render the window, but clear stencil glClearStencil(0); glClear(GL_STENCIL_BUFFER_BIT); - // and write to it + // draw window + glDisable(GL_STENCIL_TEST); + renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true, true); + glEnable(GL_STENCIL_TEST); + + // prep stencil for border glStencilFunc(GL_ALWAYS, 1, -1); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); @@ -623,8 +645,6 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, renderRectWithDamage(pBox, CColor(0,0,0,0), &damage, round); } - renderTextureInternalWithDamage(tex, pBox, a, &damage, round, false, false, true); - // then stop glStencilFunc(GL_EQUAL, 1, -1); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 76de6311..0648e73a 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -34,6 +34,10 @@ struct SCurrentRenderData { float projection[9]; pixman_region32_t* pDamage = nullptr; + + bool renderingPrimarySurface = false; + Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1); + Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1); }; struct SMonitorRenderData { @@ -55,7 +59,7 @@ public: void renderRect(wlr_box*, const CColor&, int round = 0); void renderRectWithDamage(wlr_box*, const CColor&, pixman_region32_t* damage, int round = 0); void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0); - void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool border = false); + void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardOpaque = false, bool border = false, bool allowPrimary = false); void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0, bool border = false); void makeWindowSnapshot(CWindow*); @@ -111,7 +115,7 @@ private: // returns the out FB, can be either Mirror or MirrorSwap CFramebuffer* blurMainFramebufferWithDamage(float a, wlr_box* pBox, pixman_region32_t* damage); - void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool border = false, bool noAA = false); + void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, pixman_region32_t* damage, int round = 0, bool discardOpaque = false, bool border = false, bool noAA = false, bool allowPrimary = false); void renderBorder(wlr_box*, const CColor&, int thick = 1, int round = 0); }; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index b760dac0..8118af48 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -23,8 +23,12 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { float rounding = RDATA->dontRound ? 0 : RDATA->rounding == -1 ? *PROUNDING : RDATA->rounding; - if (RDATA->surface && surface == RDATA->surface) + g_pHyprOpenGL->m_RenderData.renderingPrimarySurface = false; + + if (RDATA->surface && surface == RDATA->surface) { + g_pHyprOpenGL->m_RenderData.renderingPrimarySurface = true; g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding, RDATA->decorate); + } else g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, false, false); @@ -166,8 +170,30 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, SMonitor* pMonitor, timespec* for (auto& wd : pWindow->m_dWindowDecorations) wd->draw(pMonitor); + if (!pWindow->m_bIsX11) { + + // To everyone who makes apps with improperly aligned surfaces, + // For example chromium, or GTK devs who allow shadows on windows, + // a sincere FUCK YOU. + + wlr_box geom; + wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom); + + g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D((double)geom.x / (double)pWindow->m_uSurface.xdg->surface->current.width, (double)geom.y / (double)pWindow->m_uSurface.xdg->surface->current.height); + g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D((double)(geom.width + geom.x) / (double)pWindow->m_uSurface.xdg->surface->current.width, (double)(geom.y + geom.height) / (double)pWindow->m_uSurface.xdg->surface->current.height); + + if (g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft == Vector2D() && g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight == Vector2D(1, 1)) { + // No special UV mods needed + g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1); + g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1); + } + } + wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(pWindow), renderSurface, &renderdata); + g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1); + g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1); + if (pWindow->m_bIsX11) { if (pWindow->m_uSurface.xwayland->surface) { wlr_surface_for_each_surface(pWindow->m_uSurface.xwayland->surface, renderSurface, &renderdata);