aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/Window.hpp9
-rw-r--r--src/debug/HyprCtl.cpp27
-rw-r--r--src/events/Events.hpp1
-rw-r--r--src/events/Windows.cpp23
-rw-r--r--src/helpers/SubsurfaceTree.cpp5
-rw-r--r--src/layout/IHyprLayout.cpp4
-rw-r--r--src/managers/XWaylandManager.cpp4
-rw-r--r--src/render/OpenGL.cpp31
-rw-r--r--src/render/OpenGL.hpp2
-rw-r--r--src/render/decorations/CHyprDropShadowDecoration.cpp16
-rw-r--r--src/render/shaders/Shadow.hpp7
-rw-r--r--src/render/shaders/Textures.hpp2
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"#(