From e13d685dd7f13671ceace6a1e2c8be4a9d19903c Mon Sep 17 00:00:00 2001 From: dawsers Date: Mon, 17 Feb 2025 18:15:59 +0100 Subject: [PATCH 1/9] dispatchers: add scaleactive for per-window content scaling --- src/Compositor.cpp | 6 +++-- src/desktop/Popup.cpp | 22 +++++++++++++++--- src/desktop/Popup.hpp | 2 ++ src/desktop/Window.cpp | 2 +- src/desktop/Window.hpp | 2 ++ src/managers/KeybindManager.cpp | 27 ++++++++++++++++++++++ src/managers/KeybindManager.hpp | 1 + src/managers/input/InputManager.cpp | 5 ++-- src/protocols/core/Compositor.cpp | 10 ++++---- src/protocols/core/Compositor.hpp | 2 +- src/render/Renderer.cpp | 32 +++++++++++++++----------- src/render/Renderer.hpp | 2 +- src/render/pass/SurfacePassElement.cpp | 8 +++---- src/render/pass/SurfacePassElement.hpp | 1 + 14 files changed, 89 insertions(+), 33 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 5389844fb33..5b9a2f0fd56 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1009,11 +1009,13 @@ SP CCompositor::vectorWindowToSurface(const Vector2D& pos, P if (PPOPUP) { const auto OFF = PPOPUP->coordsRelativeToParent(); - sl = pos - pWindow->m_vRealPosition->goal() - OFF; + // The offset of the popup is in scaled coords (as the window surface has its contents scaled), + // but the popup doesn't have the surface scaled. + sl = (pos - pWindow->m_vRealPosition->goal()) * PPOPUP->getContentScale() - OFF; return PPOPUP->m_pWLSurface->resource(); } - auto [surf, local] = pWindow->m_pWLSurface->resource()->at(pos - pWindow->m_vRealPosition->goal(), true); + auto [surf, local] = pWindow->m_pWLSurface->resource()->at(pos - pWindow->m_vRealPosition->goal(), true, pWindow->m_fContentScale); if (surf) { sl = local; return surf; diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index 82767eadb96..284c7827bec 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -98,6 +98,7 @@ void CPopup::onMap() { const auto PMONITOR = g_pCompositor->getMonitorFromVector(COORDS); CBox box = m_pWLSurface->resource()->extends(); + box.scale(1.0 / getContentScale()); box.translate(COORDS).expand(4); g_pHyprRenderer->damageBox(box); @@ -132,6 +133,7 @@ void CPopup::onUnmap() { const auto COORDS = coordsGlobal(); CBox box = m_pWLSurface->resource()->extends(); + box.scale(1.0 / getContentScale()); box.translate(COORDS).expand(4); g_pHyprRenderer->damageBox(box); @@ -147,6 +149,7 @@ void CPopup::onUnmap() { return; auto box = CBox{p->coordsGlobal(), p->size()}; + box.scale(1.0 / p->getContentScale()); g_pHyprRenderer->damageBox(box); }, nullptr); @@ -186,7 +189,7 @@ void CPopup::onCommit(bool ignoreSiblings) { const auto COORDSLOCAL = coordsRelativeToParent(); if (m_vLastSize != m_pResource->surface->surface->current.size || m_bRequestedReposition || m_vLastPos != COORDSLOCAL) { - CBox box = {localToGlobal(m_vLastPos), m_vLastSize}; + CBox box = {localToGlobal(m_vLastPos), m_vLastSize / getContentScale()}; g_pHyprRenderer->damageBox(box); m_vLastSize = m_pResource->surface->surface->current.size; box = {COORDS, m_vLastSize}; @@ -198,7 +201,7 @@ void CPopup::onCommit(bool ignoreSiblings) { if (!ignoreSiblings && m_pSubsurfaceHead) m_pSubsurfaceHead->recheckDamageForSubsurfaces(); - g_pHyprRenderer->damageSurface(m_pWLSurface->resource(), COORDS.x, COORDS.y); + g_pHyprRenderer->damageSurface(m_pWLSurface->resource(), COORDS.x, COORDS.y, 1.0 / getContentScale()); m_bRequestedReposition = false; @@ -259,7 +262,11 @@ Vector2D CPopup::coordsGlobal() { } Vector2D CPopup::localToGlobal(const Vector2D& rel) { - return t1ParentCoords() + rel; + const auto coords = t1ParentCoords(); + if (!m_pWindowOwner.expired()) + return coords + rel / m_pWindowOwner->m_fContentScale; + + return coords + rel; } Vector2D CPopup::t1ParentCoords() { @@ -272,6 +279,13 @@ Vector2D CPopup::t1ParentCoords() { return {}; } +float CPopup::getContentScale() const { + if (!m_pWindowOwner.expired()) + return m_pWindowOwner->m_fContentScale; + + return 1.0f; +} + void CPopup::recheckTree() { WP curr = m_pSelf; while (curr->m_pParent) { @@ -355,6 +369,8 @@ WP CPopup::at(const Vector2D& globalCoords, bool allowsInput) { if (size == Vector2D{}) size = p->size(); + size /= getContentScale(); + const auto BOX = CBox{p->coordsGlobal() + offset, size}; if (BOX.containsPoint(globalCoords)) return p; diff --git a/src/desktop/Popup.hpp b/src/desktop/Popup.hpp index 0bca436c133..677ef9f8fbe 100644 --- a/src/desktop/Popup.hpp +++ b/src/desktop/Popup.hpp @@ -35,6 +35,8 @@ class CPopup { bool visible(); + float getContentScale() const; + // will also loop over this node void breadthfirst(std::function, void*)> fn, void* data); WP at(const Vector2D& globalCoords, bool allowsInput = false); diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 7b7f954db40..39a2458f31b 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -1750,7 +1750,7 @@ void CWindow::sendWindowSize(bool force) { // TODO: this should be decoupled from setWindowSize IMO const auto REPORTPOS = realToReportPosition(); - const auto REPORTSIZE = realToReportSize(); + const auto REPORTSIZE = realToReportSize() * m_fContentScale; if (!force && m_vPendingReportedSize == REPORTSIZE && (m_vReportedPosition == REPORTPOS || !m_bIsX11)) return; diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index bc32bab47e0..224872f2435 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -239,6 +239,8 @@ class CWindow { PHLANIMVAR m_vRealPosition; PHLANIMVAR m_vRealSize; + float m_fContentScale = 1.0f; + // for not spamming the protocols Vector2D m_vReportedPosition; Vector2D m_vReportedSize; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 4e63e6dc699..9e5f8174a1f 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -108,6 +108,7 @@ CKeybindManager::CKeybindManager() { m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace; m_mDispatchers["forcerendererreload"] = forceRendererReload; m_mDispatchers["resizeactive"] = resizeActive; + m_mDispatchers["scaleactive"] = scaleActive; m_mDispatchers["moveactive"] = moveActive; m_mDispatchers["cyclenext"] = circleNext; m_mDispatchers["focuswindowbyclass"] = focusWindow; @@ -2148,6 +2149,32 @@ SDispatchResult CKeybindManager::resizeActive(std::string args) { return {}; } +SDispatchResult CKeybindManager::scaleActive(std::string args) { + const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); + + if (!PLASTWINDOW) + return {.success = false, .error = "Window not found"}; + + std::optional scaleResult; + + try { + scaleResult = stof(args); + } catch (...) { + Debug::log(ERR, "Invalid arg \"{}\" in scaleactive!", args); + return {.success = false, .error = "Invalid scale in scaleactive!"}; + } + + float scale = scaleResult.value(); + if (scale > 0.0f) { + PLASTWINDOW->m_fContentScale = 1.0 / scale; + } else { + PLASTWINDOW->m_fContentScale = 1.0f; + } + PLASTWINDOW->sendWindowSize(); + + return {}; +} + SDispatchResult CKeybindManager::moveActive(std::string args) { const auto PLASTWINDOW = g_pCompositor->m_pLastWindow.lock(); diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 712fd58d390..d2460a31c55 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -193,6 +193,7 @@ class CKeybindManager { static SDispatchResult toggleSpecialWorkspace(std::string); static SDispatchResult forceRendererReload(std::string); static SDispatchResult resizeActive(std::string); + static SDispatchResult scaleActive(std::string); static SDispatchResult moveActive(std::string); static SDispatchResult moveWindow(std::string); static SDispatchResult resizeWindow(std::string); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 1d16f9151f4..fa7f68892ee 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -440,13 +440,14 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) { m_bEmptyFocusCursorSet = false; - Vector2D surfaceLocal = surfacePos == Vector2D(-1337, -1337) ? surfaceCoords : mouseCoords - surfacePos; + const Vector2D relMouseCoords = mouseCoords - surfacePos; + Vector2D surfaceLocal = surfacePos == Vector2D(-1337, -1337) ? surfaceCoords : (pFoundWindow? relMouseCoords * pFoundWindow->m_fContentScale : relMouseCoords); if (pFoundWindow && !pFoundWindow->m_bIsX11 && surfacePos != Vector2D(-1337, -1337)) { // calc for oversized windows... fucking bullshit. CBox geom = pFoundWindow->m_pXDGSurface->current.geometry; - surfaceLocal = mouseCoords - surfacePos + geom.pos(); + surfaceLocal = (pFoundWindow? relMouseCoords * pFoundWindow->m_fContentScale : relMouseCoords) + geom.pos(); } if (pFoundWindow && pFoundWindow->m_bIsX11) // for x11 force scale zero diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 92c3c425d7c..de6b7eea7e9 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -306,19 +306,19 @@ void CWLSurfaceResource::breadthfirst(std::function, bfHelper(surfs, fn, data); } -std::pair, Vector2D> CWLSurfaceResource::at(const Vector2D& localCoords, bool allowsInput) { +std::pair, Vector2D> CWLSurfaceResource::at(const Vector2D& localCoords, bool allowsInput, double scale) { std::vector, Vector2D>> surfs; breadthfirst([&surfs](SP surf, const Vector2D& offset, void* data) { surfs.emplace_back(std::make_pair<>(surf, offset)); }, &surfs); for (auto const& [surf, pos] : surfs | std::views::reverse) { if (!allowsInput) { const auto BOX = CBox{pos, surf->current.size}; - if (BOX.containsPoint(localCoords)) - return {surf, localCoords - pos}; + if (BOX.containsPoint(localCoords * scale)) + return {surf, localCoords * scale - pos}; } else { const auto REGION = surf->current.input.copy().intersect(CBox{{}, surf->current.size}).translate(pos); - if (REGION.containsPoint(localCoords)) - return {surf, localCoords - pos}; + if (REGION.containsPoint(localCoords * scale)) + return {surf, localCoords * scale - pos}; } } diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index aaaf9b1a9cb..c27f1d75956 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -134,7 +134,7 @@ class CWLSurfaceResource { // returns a pair: found surface (null if not found) and surface local coords. // localCoords param is relative to 0,0 of this surface - std::pair, Vector2D> at(const Vector2D& localCoords, bool allowsInput = false); + std::pair, Vector2D> at(const Vector2D& localCoords, bool allowsInput = false, double scale = 1.0); private: SP resource; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index b61f1c3eb5b..3364344f83d 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -578,6 +578,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe renderdata.texture = s->current.texture; renderdata.surface = s; renderdata.mainSurface = s == pWindow->m_pWLSurface->resource(); + renderdata.contentScale = pWindow->m_fContentScale; m_sRenderPass.add(makeShared(renderdata)); renderdata.surfaceCounter++; }, @@ -611,7 +612,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe if (!pWindow->m_bIsX11) { CBox geom = pWindow->m_pXDGSurface->current.geometry; - renderdata.pos -= geom.pos(); + renderdata.pos -= geom.pos() / pWindow->m_fContentScale; renderdata.dontRound = true; // don't round popups renderdata.pMonitor = pMonitor; renderdata.squishOversized = false; // don't squish popups @@ -638,10 +639,13 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe return; const auto pos = popup->coordsRelativeToParent(); const Vector2D oldPos = renderdata.pos; - renderdata.pos += pos; - + const float scale = popup->getContentScale(); + // pos in window coordinates + renderdata.pos += pos / scale; + renderdata.contentScale = scale; popup->m_pWLSurface->resource()->breadthfirst( [this, &renderdata](SP s, const Vector2D& offset, void* data) { + // offset in surface coordinates renderdata.localPos = offset; renderdata.texture = s->current.texture; renderdata.surface = s; @@ -1015,7 +1019,7 @@ void CHyprRenderer::renderSessionLockMissing(PHLMONITOR pMonitor) { } void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SP pSurface, PHLMONITOR pMonitor, bool main, const Vector2D& projSize, - const Vector2D& projSizeUnscaled, bool fixMisalignedFSV1) { + const Vector2D& projSizeUnscaled, bool fixMisalignedFSV1, float contentScale) { if (!pWindow || !pWindow->m_bIsX11) { static auto PEXPANDEDGES = CConfigValue("render:expand_undersized_textures"); @@ -1054,7 +1058,7 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPscale); const bool SCALE_UNAWARE = MONITOR_WL_SCALE != pSurface->current.scale && !pSurface->current.viewport.hasDestination; const auto EXPECTED_SIZE = - ((pSurface->current.viewport.hasDestination ? pSurface->current.viewport.destination : pSurface->current.bufferSize / pSurface->current.scale) * pMonitor->scale) + ((pSurface->current.viewport.hasDestination ? pSurface->current.viewport.destination : pSurface->current.bufferSize / pSurface->current.scale) * pMonitor->scale / contentScale) .round(); if (!SCALE_UNAWARE && (EXPECTED_SIZE.x < projSize.x || EXPECTED_SIZE.y < projSize.y)) { // this will not work with shm AFAIK, idk why. @@ -1079,11 +1083,11 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPm_pXDGSurface->current.geometry; // ignore X and Y, adjust uv - if (geom.x != 0 || geom.y != 0 || geom.width > projSizeUnscaled.x || geom.height > projSizeUnscaled.y) { - const auto XPERC = (double)geom.x / (double)pSurface->current.size.x; - const auto YPERC = (double)geom.y / (double)pSurface->current.size.y; - const auto WPERC = (double)(geom.x + geom.width) / (double)pSurface->current.size.x; - const auto HPERC = (double)(geom.y + geom.height) / (double)pSurface->current.size.y; + if (geom.x != 0 || geom.y != 0 || geom.width > projSizeUnscaled.x * contentScale || geom.height > projSizeUnscaled.y * contentScale) { + const auto XPERC = (double)geom.x / (double)pSurface->current.size.x / contentScale; + const auto YPERC = (double)geom.y / (double)pSurface->current.size.y / contentScale; + const auto WPERC = (double)(geom.x + geom.width) / (double)pSurface->current.size.x / contentScale; + const auto HPERC = (double)(geom.y + geom.height) / (double)pSurface->current.size.y / contentScale; const auto TOADDTL = Vector2D(XPERC * (uvBR.x - uvTL.x), YPERC * (uvBR.y - uvTL.y)); uvBR = uvBR - Vector2D((1.0 - WPERC) * (uvBR.x - uvTL.x), (1.0 - HPERC) * (uvBR.y - uvTL.y)); @@ -1094,10 +1098,10 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPm_pWLSurface->small() && !pWindow->m_pWLSurface->m_bFillIgnoreSmall) maxSize = pWindow->m_pWLSurface->getViewporterCorrectedSize(); - if (geom.width > maxSize.x) - uvBR.x = uvBR.x * (maxSize.x / geom.width); - if (geom.height > maxSize.y) - uvBR.y = uvBR.y * (maxSize.y / geom.height); + if (geom.width > maxSize.x * contentScale) + uvBR.x = uvBR.x * (maxSize.x * contentScale / geom.width); + if (geom.height > maxSize.y * contentScale) + uvBR.y = uvBR.y * (maxSize.y * contentScale / geom.height); } g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = uvTL; diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 731ed926c45..54c7abbdb3d 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -64,7 +64,7 @@ class CHyprRenderer { bool shouldRenderCursor(); void setCursorHidden(bool hide); void calculateUVForSurface(PHLWINDOW, SP, PHLMONITOR pMonitor, bool main = false, const Vector2D& projSize = {}, const Vector2D& projSizeUnscaled = {}, - bool fixMisalignedFSV1 = false); + bool fixMisalignedFSV1 = false, float contentScale = 1.0f); std::tuple getRenderTimes(PHLMONITOR pMonitor); // avg max min void renderLockscreen(PHLMONITOR pMonitor, timespec* now, const CBox& geometry); void recheckSolitaryForMonitor(PHLMONITOR pMonitor); diff --git a/src/render/pass/SurfacePassElement.cpp b/src/render/pass/SurfacePassElement.cpp index a5d3d7c001a..24bfc3ebb61 100644 --- a/src/render/pass/SurfacePassElement.cpp +++ b/src/render/pass/SurfacePassElement.cpp @@ -85,7 +85,7 @@ void CSurfacePassElement::draw(const CRegion& damage) { if (data.surface->colorManagement.valid()) Debug::log(TRACE, "FIXME: rendering surface with color management enabled, should apply necessary transformations"); - g_pHyprRenderer->calculateUVForSurface(data.pWindow, data.surface, data.pMonitor->self.lock(), data.mainSurface, windowBox.size(), PROJSIZEUNSCALED, MISALIGNEDFSV1); + g_pHyprRenderer->calculateUVForSurface(data.pWindow, data.surface, data.pMonitor->self.lock(), data.mainSurface, windowBox.size(), PROJSIZEUNSCALED, MISALIGNEDFSV1, data.contentScale); auto cancelRender = false; g_pHyprOpenGL->m_RenderData.clipRegion = visibleRegion(cancelRender); @@ -146,7 +146,7 @@ CBox CSurfacePassElement::getTexBox() { CBox windowBox; if (data.surface && data.mainSurface) { - windowBox = {(int)outputX + data.pos.x + data.localPos.x, (int)outputY + data.pos.y + data.localPos.y, data.w, data.h}; + windowBox = {(int)outputX + data.pos.x + (data.localPos.x / data.contentScale), (int)outputY + data.pos.y + (data.localPos.y / data.contentScale), data.w, data.h}; // however, if surface buffer w / h < box, we need to adjust them const auto PWINDOW = PSURFACE ? PSURFACE->getWindow() : nullptr; @@ -168,8 +168,8 @@ CBox CSurfacePassElement::getTexBox() { } } else { // here we clamp to 2, these might be some tiny specks - windowBox = {(int)outputX + data.pos.x + data.localPos.x, (int)outputY + data.pos.y + data.localPos.y, std::max((float)data.surface->current.size.x, 2.F), - std::max((float)data.surface->current.size.y, 2.F)}; + windowBox = {(int)outputX + data.pos.x + (data.localPos.x / data.contentScale), (int)outputY + data.pos.y + (data.localPos.y / data.contentScale), std::max((float)data.surface->current.size.x / data.contentScale, 2.F), + std::max((float)data.surface->current.size.y / data.contentScale, 2.F)}; if (data.pWindow && data.pWindow->m_vRealSize->isBeingAnimated() && data.surface && !data.mainSurface && data.squishOversized /* subsurface */) { // adjust subsurfaces to the window windowBox.width = (windowBox.width / data.pWindow->m_vReportedSize.x) * data.pWindow->m_vRealSize->value().x; diff --git a/src/render/pass/SurfacePassElement.hpp b/src/render/pass/SurfacePassElement.hpp index 1b6ddb0ba26..529180a11e5 100644 --- a/src/render/pass/SurfacePassElement.hpp +++ b/src/render/pass/SurfacePassElement.hpp @@ -25,6 +25,7 @@ class CSurfacePassElement : public IPassElement { float alpha = 1.F, fadeAlpha = 1.F; bool blur = false; bool blockBlurOptimization = false; + float contentScale = 1.F; // only for windows, not popups bool squishOversized = true; From 037d5450f4b845a893a2434729cf22b26e7a07a6 Mon Sep 17 00:00:00 2001 From: dawsers Date: Mon, 17 Feb 2025 20:38:33 +0100 Subject: [PATCH 2/9] fix clang-format errors --- src/Compositor.cpp | 2 +- src/desktop/Window.hpp | 2 +- src/managers/input/InputManager.cpp | 4 ++-- src/render/Renderer.cpp | 13 +++++++------ src/render/pass/SurfacePassElement.cpp | 7 ++++--- src/render/pass/SurfacePassElement.hpp | 2 +- 6 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 5b9a2f0fd56..74de81d369e 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1011,7 +1011,7 @@ SP CCompositor::vectorWindowToSurface(const Vector2D& pos, P const auto OFF = PPOPUP->coordsRelativeToParent(); // The offset of the popup is in scaled coords (as the window surface has its contents scaled), // but the popup doesn't have the surface scaled. - sl = (pos - pWindow->m_vRealPosition->goal()) * PPOPUP->getContentScale() - OFF; + sl = (pos - pWindow->m_vRealPosition->goal()) * PPOPUP->getContentScale() - OFF; return PPOPUP->m_pWLSurface->resource(); } diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 224872f2435..39a7b7eb634 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -239,7 +239,7 @@ class CWindow { PHLANIMVAR m_vRealPosition; PHLANIMVAR m_vRealSize; - float m_fContentScale = 1.0f; + float m_fContentScale = 1.0f; // for not spamming the protocols Vector2D m_vReportedPosition; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index fa7f68892ee..8e0b437f340 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -441,13 +441,13 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) { m_bEmptyFocusCursorSet = false; const Vector2D relMouseCoords = mouseCoords - surfacePos; - Vector2D surfaceLocal = surfacePos == Vector2D(-1337, -1337) ? surfaceCoords : (pFoundWindow? relMouseCoords * pFoundWindow->m_fContentScale : relMouseCoords); + Vector2D surfaceLocal = surfacePos == Vector2D(-1337, -1337) ? surfaceCoords : (pFoundWindow ? relMouseCoords * pFoundWindow->m_fContentScale : relMouseCoords); if (pFoundWindow && !pFoundWindow->m_bIsX11 && surfacePos != Vector2D(-1337, -1337)) { // calc for oversized windows... fucking bullshit. CBox geom = pFoundWindow->m_pXDGSurface->current.geometry; - surfaceLocal = (pFoundWindow? relMouseCoords * pFoundWindow->m_fContentScale : relMouseCoords) + geom.pos(); + surfaceLocal = (pFoundWindow ? relMouseCoords * pFoundWindow->m_fContentScale : relMouseCoords) + geom.pos(); } if (pFoundWindow && pFoundWindow->m_bIsX11) // for x11 force scale zero diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 3364344f83d..7bb91c2e1a2 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -574,10 +574,10 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe renderdata.surfaceCounter = 0; pWindow->m_pWLSurface->resource()->breadthfirst( [this, &renderdata, &pWindow](SP s, const Vector2D& offset, void* data) { - renderdata.localPos = offset; - renderdata.texture = s->current.texture; - renderdata.surface = s; - renderdata.mainSurface = s == pWindow->m_pWLSurface->resource(); + renderdata.localPos = offset; + renderdata.texture = s->current.texture; + renderdata.surface = s; + renderdata.mainSurface = s == pWindow->m_pWLSurface->resource(); renderdata.contentScale = pWindow->m_fContentScale; m_sRenderPass.add(makeShared(renderdata)); renderdata.surfaceCounter++; @@ -639,7 +639,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe return; const auto pos = popup->coordsRelativeToParent(); const Vector2D oldPos = renderdata.pos; - const float scale = popup->getContentScale(); + const float scale = popup->getContentScale(); // pos in window coordinates renderdata.pos += pos / scale; renderdata.contentScale = scale; @@ -1058,7 +1058,8 @@ void CHyprRenderer::calculateUVForSurface(PHLWINDOW pWindow, SPscale); const bool SCALE_UNAWARE = MONITOR_WL_SCALE != pSurface->current.scale && !pSurface->current.viewport.hasDestination; const auto EXPECTED_SIZE = - ((pSurface->current.viewport.hasDestination ? pSurface->current.viewport.destination : pSurface->current.bufferSize / pSurface->current.scale) * pMonitor->scale / contentScale) + ((pSurface->current.viewport.hasDestination ? pSurface->current.viewport.destination : pSurface->current.bufferSize / pSurface->current.scale) * pMonitor->scale / + contentScale) .round(); if (!SCALE_UNAWARE && (EXPECTED_SIZE.x < projSize.x || EXPECTED_SIZE.y < projSize.y)) { // this will not work with shm AFAIK, idk why. diff --git a/src/render/pass/SurfacePassElement.cpp b/src/render/pass/SurfacePassElement.cpp index 24bfc3ebb61..f97676bc008 100644 --- a/src/render/pass/SurfacePassElement.cpp +++ b/src/render/pass/SurfacePassElement.cpp @@ -85,7 +85,8 @@ void CSurfacePassElement::draw(const CRegion& damage) { if (data.surface->colorManagement.valid()) Debug::log(TRACE, "FIXME: rendering surface with color management enabled, should apply necessary transformations"); - g_pHyprRenderer->calculateUVForSurface(data.pWindow, data.surface, data.pMonitor->self.lock(), data.mainSurface, windowBox.size(), PROJSIZEUNSCALED, MISALIGNEDFSV1, data.contentScale); + g_pHyprRenderer->calculateUVForSurface(data.pWindow, data.surface, data.pMonitor->self.lock(), data.mainSurface, windowBox.size(), PROJSIZEUNSCALED, MISALIGNEDFSV1, + data.contentScale); auto cancelRender = false; g_pHyprOpenGL->m_RenderData.clipRegion = visibleRegion(cancelRender); @@ -168,8 +169,8 @@ CBox CSurfacePassElement::getTexBox() { } } else { // here we clamp to 2, these might be some tiny specks - windowBox = {(int)outputX + data.pos.x + (data.localPos.x / data.contentScale), (int)outputY + data.pos.y + (data.localPos.y / data.contentScale), std::max((float)data.surface->current.size.x / data.contentScale, 2.F), - std::max((float)data.surface->current.size.y / data.contentScale, 2.F)}; + windowBox = {(int)outputX + data.pos.x + (data.localPos.x / data.contentScale), (int)outputY + data.pos.y + (data.localPos.y / data.contentScale), + std::max((float)data.surface->current.size.x / data.contentScale, 2.F), std::max((float)data.surface->current.size.y / data.contentScale, 2.F)}; if (data.pWindow && data.pWindow->m_vRealSize->isBeingAnimated() && data.surface && !data.mainSurface && data.squishOversized /* subsurface */) { // adjust subsurfaces to the window windowBox.width = (windowBox.width / data.pWindow->m_vReportedSize.x) * data.pWindow->m_vRealSize->value().x; diff --git a/src/render/pass/SurfacePassElement.hpp b/src/render/pass/SurfacePassElement.hpp index 529180a11e5..af6ac42346d 100644 --- a/src/render/pass/SurfacePassElement.hpp +++ b/src/render/pass/SurfacePassElement.hpp @@ -25,7 +25,7 @@ class CSurfacePassElement : public IPassElement { float alpha = 1.F, fadeAlpha = 1.F; bool blur = false; bool blockBlurOptimization = false; - float contentScale = 1.F; + float contentScale = 1.F; // only for windows, not popups bool squishOversized = true; From c85b6f91ab6e5f831c396ce670472a90e5b9e1b7 Mon Sep 17 00:00:00 2001 From: dawsers Date: Tue, 18 Feb 2025 01:26:18 +0100 Subject: [PATCH 3/9] windowrule: added contentscale property --- src/Compositor.cpp | 2 +- src/config/ConfigManager.hpp | 4 +++- src/desktop/Popup.cpp | 4 ++-- src/desktop/Window.cpp | 14 +++++++++++++- src/desktop/Window.hpp | 5 +++-- src/desktop/WindowRule.cpp | 4 +++- src/desktop/WindowRule.hpp | 3 ++- src/managers/KeybindManager.cpp | 7 +++++-- src/managers/input/InputManager.cpp | 4 ++-- src/render/Renderer.cpp | 4 ++-- 10 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 74de81d369e..8cd0d0ef25e 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1015,7 +1015,7 @@ SP CCompositor::vectorWindowToSurface(const Vector2D& pos, P return PPOPUP->m_pWLSurface->resource(); } - auto [surf, local] = pWindow->m_pWLSurface->resource()->at(pos - pWindow->m_vRealPosition->goal(), true, pWindow->m_fContentScale); + auto [surf, local] = pWindow->m_pWLSurface->resource()->at(pos - pWindow->m_vRealPosition->goal(), true, pWindow->getContentScale()); if (surf) { sl = local; return surf; diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index b914a3a35c2..a8b46ffe3ab 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -258,7 +258,9 @@ class CConfigManager { std::unordered_map*(PHLWINDOW)>> mfWindowProperties = { {"roundingpower", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.roundingPower; }}, {"scrollmouse", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollMouse; }}, - {"scrolltouchpad", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollTouchpad; }}}; + {"scrolltouchpad", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollTouchpad; }}, + {"contentscale", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.contentScale; }}, + }; bool m_bWantsMonitorReload = false; bool m_bNoMonitorReload = false; diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index 284c7827bec..ab392d0f6dc 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -264,7 +264,7 @@ Vector2D CPopup::coordsGlobal() { Vector2D CPopup::localToGlobal(const Vector2D& rel) { const auto coords = t1ParentCoords(); if (!m_pWindowOwner.expired()) - return coords + rel / m_pWindowOwner->m_fContentScale; + return coords + rel / m_pWindowOwner->getContentScale(); return coords + rel; } @@ -281,7 +281,7 @@ Vector2D CPopup::t1ParentCoords() { float CPopup::getContentScale() const { if (!m_pWindowOwner.expired()) - return m_pWindowOwner->m_fContentScale; + return m_pWindowOwner->getContentScale(); return 1.0f; } diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 39a2458f31b..9eaffa5de3f 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -767,6 +767,14 @@ void CWindow::applyDynamicRule(const SP& r) { } catch (std::exception& e) { Debug::log(ERR, "minsize rule \"{}\" failed with: {}", r->szRule, e.what()); } break; } + case CWindowRule::RULE_CONTENTSCALE: { + try { + const auto SCALE = std::stof(r->szRule.substr(13)); + m_sWindowData.contentScale = CWindowOverridableVar(1.0f / SCALE, priority); + sendWindowSize(); + } catch (std::exception& e) { Debug::log(ERR, "contentscale rule \"{}\" failed with: {}", r->szRule, e.what()); } + break; + } case CWindowRule::RULE_RENDERUNFOCUSED: { m_sWindowData.renderUnfocused = CWindowOverridableVar(true, priority); g_pHyprRenderer->addWindowToRenderUnfocused(m_pSelf.lock()); @@ -1223,6 +1231,10 @@ float CWindow::getScrollTouchpad() { return m_sWindowData.scrollTouchpad.valueOr(*PTOUCHPADSCROLLFACTOR); } +float CWindow::getContentScale() { + return m_sWindowData.contentScale.valueOr(1.0f); +} + bool CWindow::canBeTorn() { static auto PTEARING = CConfigValue("general:allow_tearing"); return m_sWindowData.tearing.valueOr(m_bTearingHint) && *PTEARING; @@ -1750,7 +1762,7 @@ void CWindow::sendWindowSize(bool force) { // TODO: this should be decoupled from setWindowSize IMO const auto REPORTPOS = realToReportPosition(); - const auto REPORTSIZE = realToReportSize() * m_fContentScale; + const auto REPORTSIZE = realToReportSize() * getContentScale(); if (!force && m_vPendingReportedSize == REPORTSIZE && (m_vReportedPosition == REPORTPOS || !m_bIsX11)) return; diff --git a/src/desktop/Window.hpp b/src/desktop/Window.hpp index 39a7b7eb634..5321cde08fd 100644 --- a/src/desktop/Window.hpp +++ b/src/desktop/Window.hpp @@ -198,6 +198,8 @@ struct SWindowData { CWindowOverridableVar activeBorderColor; CWindowOverridableVar inactiveBorderColor; + + CWindowOverridableVar contentScale; }; struct SInitialWorkspaceToken { @@ -239,8 +241,6 @@ class CWindow { PHLANIMVAR m_vRealPosition; PHLANIMVAR m_vRealSize; - float m_fContentScale = 1.0f; - // for not spamming the protocols Vector2D m_vReportedPosition; Vector2D m_vReportedSize; @@ -437,6 +437,7 @@ class CWindow { int getRealBorderSize(); float getScrollMouse(); float getScrollTouchpad(); + float getContentScale(); void updateWindowData(); void updateWindowData(const struct SWorkspaceRule&); void onBorderAngleAnimEnd(WP pav); diff --git a/src/desktop/WindowRule.cpp b/src/desktop/WindowRule.cpp index fea2d43b2cf..4dfeb4bd9c1 100644 --- a/src/desktop/WindowRule.cpp +++ b/src/desktop/WindowRule.cpp @@ -10,7 +10,7 @@ static const auto RULES = std::unordered_set{ static const auto RULES_PREFIX = std::unordered_set{ "animation", "bordercolor", "bordersize", "center", "content", "fullscreenstate", "group", "idleinhibit", "maxsize", "minsize", "monitor", "move", "opacity", "plugin:", "prop", "pseudo", "rounding", "roundingpower", "scrollmouse", "scrolltouchpad", - "size", "suppressevent", "tag", "workspace", "xray", + "size", "suppressevent", "tag", "workspace", "xray", "contentscale", }; CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool isV2, bool isExecRule) : szValue(value), szRule(rule), v2(isV2), execRule(isExecRule) { @@ -55,6 +55,8 @@ CWindowRule::CWindowRule(const std::string& rule, const std::string& value, bool ruleType = RULE_MAXSIZE; else if (rule.starts_with("minsize")) ruleType = RULE_MINSIZE; + else if (rule.starts_with("contentscale")) + ruleType = RULE_CONTENTSCALE; else if (rule.starts_with("monitor")) ruleType = RULE_MONITOR; else if (rule.starts_with("move")) diff --git a/src/desktop/WindowRule.hpp b/src/desktop/WindowRule.hpp index 50e221f3e8d..f436a07612d 100644 --- a/src/desktop/WindowRule.hpp +++ b/src/desktop/WindowRule.hpp @@ -26,6 +26,7 @@ class CWindowRule { RULE_IDLEINHIBIT, RULE_MAXSIZE, RULE_MINSIZE, + RULE_CONTENTSCALE, RULE_MONITOR, RULE_MOVE, RULE_OPACITY, @@ -67,4 +68,4 @@ class CWindowRule { CRuleRegexContainer rInitialTitle; CRuleRegexContainer rInitialClass; CRuleRegexContainer rV1Regex; -}; \ No newline at end of file +}; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 9e5f8174a1f..1e234e1243b 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2166,9 +2166,9 @@ SDispatchResult CKeybindManager::scaleActive(std::string args) { float scale = scaleResult.value(); if (scale > 0.0f) { - PLASTWINDOW->m_fContentScale = 1.0 / scale; + PLASTWINDOW->m_sWindowData.contentScale = CWindowOverridableVar(1.0f / scale, PRIORITY_SET_PROP); } else { - PLASTWINDOW->m_fContentScale = 1.0f; + PLASTWINDOW->m_sWindowData.contentScale.unset(PRIORITY_SET_PROP); } PLASTWINDOW->sendWindowSize(); @@ -3162,6 +3162,9 @@ SDispatchResult CKeybindManager::setProp(std::string args) { PWINDOW->m_sWindowData.minSize = CWindowOverridableVar(configStringToVector2D(VAL), PRIORITY_SET_PROP); PWINDOW->clampWindowSize(PWINDOW->m_sWindowData.minSize.value(), std::nullopt); PWINDOW->setHidden(false); + } else if (PROP == "contentscale") { + PWINDOW->m_sWindowData.contentScale = CWindowOverridableVar(1.0f / std::stof(VAL), PRIORITY_SET_PROP); + PWINDOW->sendWindowSize(); } else if (PROP == "alpha") { PWINDOW->m_sWindowData.alpha = CWindowOverridableVar(SAlphaValue{std::stof(VAL), PWINDOW->m_sWindowData.alpha.valueOrDefault().m_bOverride}, PRIORITY_SET_PROP); } else if (PROP == "alphainactive") { diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 8e0b437f340..70ae3d6aad6 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -441,13 +441,13 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus, bool mouse) { m_bEmptyFocusCursorSet = false; const Vector2D relMouseCoords = mouseCoords - surfacePos; - Vector2D surfaceLocal = surfacePos == Vector2D(-1337, -1337) ? surfaceCoords : (pFoundWindow ? relMouseCoords * pFoundWindow->m_fContentScale : relMouseCoords); + Vector2D surfaceLocal = surfacePos == Vector2D(-1337, -1337) ? surfaceCoords : (pFoundWindow ? relMouseCoords * pFoundWindow->getContentScale() : relMouseCoords); if (pFoundWindow && !pFoundWindow->m_bIsX11 && surfacePos != Vector2D(-1337, -1337)) { // calc for oversized windows... fucking bullshit. CBox geom = pFoundWindow->m_pXDGSurface->current.geometry; - surfaceLocal = (pFoundWindow ? relMouseCoords * pFoundWindow->m_fContentScale : relMouseCoords) + geom.pos(); + surfaceLocal = (pFoundWindow ? relMouseCoords * pFoundWindow->getContentScale() : relMouseCoords) + geom.pos(); } if (pFoundWindow && pFoundWindow->m_bIsX11) // for x11 force scale zero diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 7bb91c2e1a2..199148dc1e7 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -578,7 +578,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe renderdata.texture = s->current.texture; renderdata.surface = s; renderdata.mainSurface = s == pWindow->m_pWLSurface->resource(); - renderdata.contentScale = pWindow->m_fContentScale; + renderdata.contentScale = pWindow->getContentScale(); m_sRenderPass.add(makeShared(renderdata)); renderdata.surfaceCounter++; }, @@ -612,7 +612,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe if (!pWindow->m_bIsX11) { CBox geom = pWindow->m_pXDGSurface->current.geometry; - renderdata.pos -= geom.pos() / pWindow->m_fContentScale; + renderdata.pos -= geom.pos() / pWindow->getContentScale(); renderdata.dontRound = true; // don't round popups renderdata.pMonitor = pMonitor; renderdata.squishOversized = false; // don't squish popups From 6ba4e541a09559e6fdc040c928ceaf87fb012d5a Mon Sep 17 00:00:00 2001 From: dawsers Date: Fri, 21 Feb 2025 22:21:18 +0100 Subject: [PATCH 4/9] dispatchers: Allow relative numbers for scaleactive --- src/managers/KeybindManager.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 1e234e1243b..3529fa45045 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2156,20 +2156,28 @@ SDispatchResult CKeybindManager::scaleActive(std::string args) { return {.success = false, .error = "Window not found"}; std::optional scaleResult; + bool exact = false; - try { - scaleResult = stof(args); - } catch (...) { + if (args.starts_with("exact")) { + exact = true; + scaleResult = getPlusMinusKeywordResult(args.substr(5), 0); + } else + scaleResult = getPlusMinusKeywordResult(args, 0); + + if (!scaleResult.has_value()) { Debug::log(ERR, "Invalid arg \"{}\" in scaleactive!", args); - return {.success = false, .error = "Invalid scale in scaleactive!"}; + return {.success = false, .error = "Invalid scale argument in scaleactive!"}; } float scale = scaleResult.value(); - if (scale > 0.0f) { + if (!exact) + scale += 1.0 / PLASTWINDOW->m_sWindowData.contentScale.valueOr(1.0f); + + if (scale > 0.0f) PLASTWINDOW->m_sWindowData.contentScale = CWindowOverridableVar(1.0f / scale, PRIORITY_SET_PROP); - } else { + else PLASTWINDOW->m_sWindowData.contentScale.unset(PRIORITY_SET_PROP); - } + PLASTWINDOW->sendWindowSize(); return {}; From 0d3ccec4856bf1fde6486d4c3696ed3064d43e3f Mon Sep 17 00:00:00 2001 From: dawsers Date: Tue, 25 Feb 2025 18:53:14 +0100 Subject: [PATCH 5/9] dispatchers: scaleactive fix for some popup locations --- src/desktop/Popup.cpp | 6 +++++- src/render/pass/SurfacePassElement.cpp | 8 ++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/desktop/Popup.cpp b/src/desktop/Popup.cpp index ab392d0f6dc..074a366e5ef 100644 --- a/src/desktop/Popup.cpp +++ b/src/desktop/Popup.cpp @@ -226,7 +226,11 @@ void CPopup::reposition() { if (!PMONITOR) return; - CBox box = {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; + CBox box = {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; + const auto scale = getContentScale(); + box.w = COORDS.x + (box.w - COORDS.x) * scale; + box.h = COORDS.y + (box.h - COORDS.y) * scale; + m_pResource->applyPositioning(box, COORDS); } diff --git a/src/render/pass/SurfacePassElement.cpp b/src/render/pass/SurfacePassElement.cpp index f97676bc008..a19a2a814e0 100644 --- a/src/render/pass/SurfacePassElement.cpp +++ b/src/render/pass/SurfacePassElement.cpp @@ -179,10 +179,10 @@ CBox CSurfacePassElement::getTexBox() { } if (data.squishOversized) { - if (data.localPos.x + windowBox.width > data.w) - windowBox.width = data.w - data.localPos.x; - if (data.localPos.y + windowBox.height > data.h) - windowBox.height = data.h - data.localPos.y; + if (data.localPos.x / data.contentScale + windowBox.width > data.w) + windowBox.width = data.w - data.localPos.x / data.contentScale; + if (data.localPos.y / data.contentScale + windowBox.height > data.h) + windowBox.height = data.h - data.localPos.y / data.contentScale; } return windowBox; From d562ee0e29007c301a18ca767b766584156a4861 Mon Sep 17 00:00:00 2001 From: dawsers Date: Sun, 2 Mar 2025 14:52:08 +0100 Subject: [PATCH 6/9] clang-format from merged files --- src/debug/HyprCtl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index eae596fa4d6..3f955f6cecf 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -264,8 +264,8 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) { escapeJSONStrings(!w->m_pWorkspace ? "" : w->m_pWorkspace->m_szName), ((int)w->m_bIsFloating == 1 ? "true" : "false"), (w->m_bIsPseudotiled ? "true" : "false"), (int64_t)w->monitorID(), escapeJSONStrings(w->m_szClass), escapeJSONStrings(w->m_szTitle), escapeJSONStrings(w->m_szInitialClass), escapeJSONStrings(w->m_szInitialTitle), w->getPID(), ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"), - (uint8_t)w->m_sFullscreenState.internal, (uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format), - (uintptr_t)w->m_pSwallowed.get(), getFocusHistoryID(w), (g_pInputManager->isWindowInhibiting(w, false) ? "true" : "false")); + (uint8_t)w->m_sFullscreenState.internal, (uint8_t)w->m_sFullscreenState.client, getGroupedData(w, format), getTagsData(w, format), (uintptr_t)w->m_pSwallowed.get(), + getFocusHistoryID(w), (g_pInputManager->isWindowInhibiting(w, false) ? "true" : "false")); } else { return std::format( "Window {:x} -> {}:\n\tmapped: {}\n\thidden: {}\n\tat: {},{}\n\tsize: {},{}\n\tworkspace: {} ({})\n\tfloating: {}\n\tpseudo: {}\n\tmonitor: {}\n\tclass: {}\n\ttitle: " From 613fe44a24b03b6dbc688872b50e33d3322538f7 Mon Sep 17 00:00:00 2001 From: dawsers Date: Mon, 3 Mar 2025 22:59:33 +0100 Subject: [PATCH 7/9] dispatchers: scaleactive cap minimum to 0.25 --- src/managers/KeybindManager.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 73a3fb31a51..37239ca8c4a 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2173,9 +2173,10 @@ SDispatchResult CKeybindManager::scaleActive(std::string args) { if (!exact) scale += 1.0 / PLASTWINDOW->m_sWindowData.contentScale.valueOr(1.0f); - if (scale > 0.0f) - PLASTWINDOW->m_sWindowData.contentScale = CWindowOverridableVar(1.0f / scale, PRIORITY_SET_PROP); - else + if (scale > 0.0f) { + if (scale >= 0.25f) + PLASTWINDOW->m_sWindowData.contentScale = CWindowOverridableVar(1.0f / scale, PRIORITY_SET_PROP); + } else PLASTWINDOW->m_sWindowData.contentScale.unset(PRIORITY_SET_PROP); PLASTWINDOW->sendWindowSize(); From 4ee1b6e996119aaea0ab2f1ed0a5c40216bbd643 Mon Sep 17 00:00:00 2001 From: dawsers Date: Tue, 4 Mar 2025 10:24:44 +0100 Subject: [PATCH 8/9] dispatchers: scaleactive allow threshold if multiplier not standard --- src/managers/KeybindManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 37239ca8c4a..169247f0da6 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2174,8 +2174,8 @@ SDispatchResult CKeybindManager::scaleActive(std::string args) { scale += 1.0 / PLASTWINDOW->m_sWindowData.contentScale.valueOr(1.0f); if (scale > 0.0f) { - if (scale >= 0.25f) - PLASTWINDOW->m_sWindowData.contentScale = CWindowOverridableVar(1.0f / scale, PRIORITY_SET_PROP); + scale = std::max(scale, 0.25f); + PLASTWINDOW->m_sWindowData.contentScale = CWindowOverridableVar(1.0f / scale, PRIORITY_SET_PROP); } else PLASTWINDOW->m_sWindowData.contentScale.unset(PRIORITY_SET_PROP); From a6024aef593a6c16f5dcfc605bb8d62b6bf5f377 Mon Sep 17 00:00:00 2001 From: dawsers Date: Tue, 4 Mar 2025 10:41:43 +0100 Subject: [PATCH 9/9] clang-format --- src/managers/KeybindManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 169247f0da6..a5eb1d4b49c 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2174,7 +2174,7 @@ SDispatchResult CKeybindManager::scaleActive(std::string args) { scale += 1.0 / PLASTWINDOW->m_sWindowData.contentScale.valueOr(1.0f); if (scale > 0.0f) { - scale = std::max(scale, 0.25f); + scale = std::max(scale, 0.25f); PLASTWINDOW->m_sWindowData.contentScale = CWindowOverridableVar(1.0f / scale, PRIORITY_SET_PROP); } else PLASTWINDOW->m_sWindowData.contentScale.unset(PRIORITY_SET_PROP);