diff options
-rw-r--r-- | src/Window.hpp | 9 | ||||
-rw-r--r-- | src/debug/HyprCtl.cpp | 27 | ||||
-rw-r--r-- | src/events/Events.hpp | 1 | ||||
-rw-r--r-- | src/events/Windows.cpp | 23 | ||||
-rw-r--r-- | src/helpers/SubsurfaceTree.cpp | 5 | ||||
-rw-r--r-- | src/layout/IHyprLayout.cpp | 4 | ||||
-rw-r--r-- | src/managers/XWaylandManager.cpp | 4 | ||||
-rw-r--r-- | src/render/OpenGL.cpp | 31 | ||||
-rw-r--r-- | src/render/OpenGL.hpp | 2 | ||||
-rw-r--r-- | src/render/decorations/CHyprDropShadowDecoration.cpp | 16 | ||||
-rw-r--r-- | src/render/shaders/Shadow.hpp | 7 | ||||
-rw-r--r-- | src/render/shaders/Textures.hpp | 2 |
12 files changed, 74 insertions, 57 deletions
diff --git a/src/Window.hpp b/src/Window.hpp index afff3ccf..4e1ab9c1 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -185,6 +185,7 @@ class CWindow { DYNLISTENER(setOverrideRedirect); DYNLISTENER(associateX11); DYNLISTENER(dissociateX11); + DYNLISTENER(ackConfigure); // DYNLISTENER(newSubsurfaceWindow); CWLSurface m_pWLSurface; @@ -204,9 +205,11 @@ class CWindow { CAnimatedVariable m_vRealSize; // for not spamming the protocols - Vector2D m_vReportedPosition; - Vector2D m_vReportedSize; - Vector2D m_vPendingReportedSize; + Vector2D m_vReportedPosition; + Vector2D m_vReportedSize; + Vector2D m_vPendingReportedSize; + std::optional<std::pair<uint32_t, Vector2D>> m_pPendingSizeAck; + std::vector<std::pair<uint32_t, Vector2D>> m_vPendingSizeAcks; // for restoring floating statuses Vector2D m_vLastFloatingSize; diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index b274b244..c09251a8 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -105,27 +105,20 @@ static std::string getGroupedData(CWindow* w, HyprCtl::eHyprCtlOutputFormat form if (!w->m_sGroupData.pNextWindow) return isJson ? "" : "0"; - std::vector<CWindow*> groupMembers; - - CWindow* curr = w; - do { - groupMembers.push_back(curr); - curr = curr->m_sGroupData.pNextWindow; - } while (curr != w); - - const auto comma = isJson ? ", " : ","; std::ostringstream result; - bool first = true; - for (auto& gw : groupMembers) { - if (first) - first = false; - else - result << comma; + CWindow* head = w->getGroupHead(); + CWindow* curr = head; + while (true) { if (isJson) - result << std::format("\"0x{:x}\"", (uintptr_t)gw); + result << std::format("\"0x{:x}\"", (uintptr_t)curr); else - result << std::format("{:x}", (uintptr_t)gw); + result << std::format("{:x}", (uintptr_t)curr); + curr = curr->m_sGroupData.pNextWindow; + // We've wrapped around to the start, break out without trailing comma + if (curr == head) + break; + result << (isJson ? ", " : ","); } return result.str(); diff --git a/src/events/Events.hpp b/src/events/Events.hpp index fc68880e..371586cc 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -62,6 +62,7 @@ namespace Events { DYNLISTENFUNC(setOverrideRedirect); DYNLISTENFUNC(associateX11); DYNLISTENFUNC(dissociateX11); + DYNLISTENFUNC(ackConfigure); // Window subsurfaces // LISTENER(newSubsurfaceWindow); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index f131efa4..e44fa0a9 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -504,6 +504,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->hyprListener_requestResize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_resize, &Events::listener_requestResize, PWINDOW, "XDG Window Late"); PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW, "XDG Window Late"); + PWINDOW->hyprListener_ackConfigure.initCallback(&PWINDOW->m_uSurface.xdg->events.ack_configure, &Events::listener_ackConfigure, PWINDOW, "XDG Window Late"); } else { PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW, "XWayland Window Late"); @@ -682,6 +683,7 @@ void Events::listener_unmapWindow(void* owner, void* data) { PWINDOW->hyprListener_requestMove.removeCallback(); PWINDOW->hyprListener_requestResize.removeCallback(); PWINDOW->hyprListener_fullscreenWindow.removeCallback(); + PWINDOW->hyprListener_ackConfigure.removeCallback(); } else { Debug::log(LOG, "Unregistered late callbacks XWL"); PWINDOW->hyprListener_fullscreenWindow.removeCallback(); @@ -788,13 +790,32 @@ void Events::listener_unmapWindow(void* owner, void* data) { PWINDOW->onUnmap(); } +void Events::listener_ackConfigure(void* owner, void* data) { + CWindow* PWINDOW = (CWindow*)owner; + const auto E = (wlr_xdg_surface_configure*)data; + + // find last matching serial + const auto SERIAL = std::find_if(PWINDOW->m_vPendingSizeAcks.rbegin(), PWINDOW->m_vPendingSizeAcks.rend(), [&](const auto& e) { return e.first == E->serial; }); + + if (SERIAL == PWINDOW->m_vPendingSizeAcks.rend()) + return; + + PWINDOW->m_pPendingSizeAck = *SERIAL; + std::erase_if(PWINDOW->m_vPendingSizeAcks, [&](const auto& el) { return el.first == SERIAL->first; }); +} + void Events::listener_commitWindow(void* owner, void* data) { CWindow* PWINDOW = (CWindow*)owner; if (!PWINDOW->m_bMappedX11 || PWINDOW->isHidden() || (PWINDOW->m_bIsX11 && !PWINDOW->m_bMappedX11)) return; - PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged. + if (PWINDOW->m_bIsX11) + PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged. + else if (PWINDOW->m_pPendingSizeAck.has_value()) { + PWINDOW->m_vReportedSize = PWINDOW->m_pPendingSizeAck->second; + PWINDOW->m_pPendingSizeAck.reset(); + } PWINDOW->updateSurfaceOutputs(); diff --git a/src/helpers/SubsurfaceTree.cpp b/src/helpers/SubsurfaceTree.cpp index 84ba5cbb..c10d45e1 100644 --- a/src/helpers/SubsurfaceTree.cpp +++ b/src/helpers/SubsurfaceTree.cpp @@ -248,14 +248,13 @@ void Events::listener_commitSubsurface(void* owner, void* data) { g_pHyprRenderer->damageSurface(pNode->pSurface->wlr(), lx, ly, SCALE); if (pNode->pWindowOwner) { - // update reported size. Some windows do not send a ::commit afterwards. Odd. - pNode->pWindowOwner->m_vReportedSize = pNode->pWindowOwner->m_vPendingReportedSize; + if (pNode->pWindowOwner->m_bIsX11) + pNode->pWindowOwner->m_vReportedSize = pNode->pWindowOwner->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged. // tearing: if solitary, redraw it. This still might be a single surface window const auto PMONITOR = g_pCompositor->getMonitorFromID(pNode->pWindowOwner->m_iMonitorID); if (PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->canBeTorn() && PMONITOR->tearingState.canTear && pNode->pSurface->wlr()->current.committed & WLR_SURFACE_STATE_BUFFER) { - CRegion damageBox; wlr_surface_get_effective_damage(pNode->pSurface->wlr(), damageBox.pixman()); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index c5ed1199..abc1aeda 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -162,8 +162,10 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) { g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv()); g_pCompositor->changeWindowZOrder(pWindow, true); - } else + } else { pWindow->m_vPendingReportedSize = pWindow->m_vRealSize.goalv(); + pWindow->m_vReportedSize = pWindow->m_vPendingReportedSize; + } } void IHyprLayout::onBeginDragWindow() { diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 04fbaf21..04fcf967 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -162,7 +162,7 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f windowPos = windowPos + PMONITOR->vecXWaylandPosition; // move to correct position for xwayland } - if (!force && ((pWindow->m_vReportedSize == size && windowPos == pWindow->m_vReportedPosition) || (pWindow->m_vReportedSize == size && !pWindow->m_bIsX11))) + if (!force && ((pWindow->m_vPendingReportedSize == size && windowPos == pWindow->m_vReportedPosition) || (pWindow->m_vPendingReportedSize == size && !pWindow->m_bIsX11))) return; pWindow->m_vReportedPosition = windowPos; @@ -180,7 +180,7 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f if (pWindow->m_bIsX11) wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, windowPos.x, windowPos.y, size.x, size.y); else - wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y); + pWindow->m_vPendingSizeAcks.push_back(std::make_pair<>(wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y), size.floor())); } void CHyprXWaylandManager::setWindowStyleTiled(CWindow* pWindow, uint32_t edgez) { diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index cf1c46e0..826854ed 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -348,21 +348,18 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shBLURFINISH.brightness = glGetUniformLocation(prog, "brightness"); m_RenderData.pCurrentMonData->m_shBLURFINISH.noise = glGetUniformLocation(prog, "noise"); - prog = createProgram(QUADVERTSRC, FRAGSHADOW); - m_RenderData.pCurrentMonData->m_shSHADOW.program = prog; - m_RenderData.pCurrentMonData->m_shSHADOW.proj = glGetUniformLocation(prog, "proj"); - m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos"); - m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord"); - m_RenderData.pCurrentMonData->m_shSHADOW.matteTexAttrib = glGetAttribLocation(prog, "texcoordMatte"); - m_RenderData.pCurrentMonData->m_shSHADOW.alphaMatte = glGetUniformLocation(prog, "alphaMatte"); - m_RenderData.pCurrentMonData->m_shSHADOW.topLeft = glGetUniformLocation(prog, "topLeft"); - m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight"); - m_RenderData.pCurrentMonData->m_shSHADOW.fullSize = glGetUniformLocation(prog, "fullSize"); - m_RenderData.pCurrentMonData->m_shSHADOW.radius = glGetUniformLocation(prog, "radius"); - m_RenderData.pCurrentMonData->m_shSHADOW.range = glGetUniformLocation(prog, "range"); - m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower"); - m_RenderData.pCurrentMonData->m_shSHADOW.color = glGetUniformLocation(prog, "color"); - m_RenderData.pCurrentMonData->m_shSHADOW.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte"); + prog = createProgram(QUADVERTSRC, FRAGSHADOW); + m_RenderData.pCurrentMonData->m_shSHADOW.program = prog; + m_RenderData.pCurrentMonData->m_shSHADOW.proj = glGetUniformLocation(prog, "proj"); + m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos"); + m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord"); + m_RenderData.pCurrentMonData->m_shSHADOW.topLeft = glGetUniformLocation(prog, "topLeft"); + m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight"); + m_RenderData.pCurrentMonData->m_shSHADOW.fullSize = glGetUniformLocation(prog, "fullSize"); + m_RenderData.pCurrentMonData->m_shSHADOW.radius = glGetUniformLocation(prog, "radius"); + m_RenderData.pCurrentMonData->m_shSHADOW.range = glGetUniformLocation(prog, "range"); + m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower"); + m_RenderData.pCurrentMonData->m_shSHADOW.color = glGetUniformLocation(prog, "color"); prog = createProgram(QUADVERTSRC, FRAGBORDER1); m_RenderData.pCurrentMonData->m_shBORDER1.program = prog; @@ -1721,7 +1718,7 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) { m_bEndFrame = false; } -void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, float a) { +void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const CColor& color, float a) { RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!"); RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!"); RASSERT(m_pCurrentWindow, "Tried to render shadow without a window!"); @@ -1740,7 +1737,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, float const auto SHADOWPOWER = std::clamp((int)*PSHADOWPOWER, 1, 4); - const auto col = m_pCurrentWindow->m_cRealShadowColor.col(); + const auto col = color; float matrix[9]; wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 0c6ef13c..8c412302 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -113,7 +113,7 @@ class CHyprOpenGLImpl { void renderTexture(wlr_texture*, CBox*, float a, int round = 0, bool allowCustomUV = false); void renderTexture(const CTexture&, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); void renderTextureWithBlur(const CTexture&, CBox*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); - void renderRoundedShadow(CBox*, int round, int range, float a = 1.0); + void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0); void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); void renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte); diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 26807dcd..b4319494 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -124,14 +124,22 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D return; // prevent assert failed alphaFB.bind(); - g_pHyprOpenGL->clear(CColor(0, 0, 0, 0)); - g_pHyprOpenGL->renderRect(&windowBox, CColor(1.0, 1.0, 1.0, 1.0), ROUNDING * pMonitor->scale); + // build the matte + // 10-bit formats have dogshit alpha channels, so we have to use the matte to its fullest. + // first, clear with black (fully transparent) + g_pHyprOpenGL->clear(CColor(0, 0, 0, 1)); + + // render white shadow + g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CColor(1, 1, 1, 1), a); + + // render black window box ("clip") + g_pHyprOpenGL->renderRect(&windowBox, CColor(0, 0, 0, 1.0), ROUNDING * pMonitor->scale); alphaSwapFB.bind(); - g_pHyprOpenGL->clear(CColor(0, 0, 0, 0)); - g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a); + // alpha swap just has the shadow color. It will be the "texture" to render. + g_pHyprOpenGL->clear(m_pWindow->m_cRealShadowColor.col()); LASTFB->bind(); diff --git a/src/render/shaders/Shadow.hpp b/src/render/shaders/Shadow.hpp index f9bdeb8d..2c7b07b2 100644 --- a/src/render/shaders/Shadow.hpp +++ b/src/render/shaders/Shadow.hpp @@ -5,9 +5,7 @@ inline const std::string FRAGSHADOW = R"#( precision mediump float; varying vec4 v_color; -uniform sampler2D alphaMatte; varying vec2 v_texcoord; -varying vec2 v_texcoordMatte; uniform vec2 topLeft; uniform vec2 bottomRight; @@ -15,7 +13,6 @@ uniform vec2 fullSize; uniform float radius; uniform float range; uniform float shadowPower; -uniform int useAlphaMatte; float pixAlphaRoundedDistance(float distanceToCorner) { if (distanceToCorner > radius) { @@ -77,10 +74,6 @@ void main() { } } - if (useAlphaMatte == 1) { - pixColor[3] *= 1.0 - texture2D(alphaMatte, v_texcoordMatte)[3]; - } - if (pixColor[3] == 0.0) { discard; return; } diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index 15e80410..e0a2b498 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -137,7 +137,7 @@ uniform sampler2D tex; uniform sampler2D texMatte; void main() { - gl_FragColor = texture2D(tex, v_texcoord) * (1.0 - texture2D(texMatte, v_texcoord)[3]); + gl_FragColor = texture2D(tex, v_texcoord) * texture2D(texMatte, v_texcoord)[0]; // I know it only uses R, but matte should be black/white anyways. })#"; inline const std::string TEXFRAGSRCRGBX = R"#( |