summaryrefslogtreecommitdiff
path: root/src/desktop/Window.cpp
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2025-12-08 15:04:40 +0000
committerGitHub <noreply@github.com>2025-12-08 15:04:40 +0000
commit920353370bba555010506a1c0b204675c60362fe (patch)
tree87ba1036ecad6294a9c86dfc828ed2a356c810bd /src/desktop/Window.cpp
parent834f019bab5df85b912a7aab7054fc8306f7c52a (diff)
desktop: cleanup, unify desktop elements as views (#12563)
Diffstat (limited to 'src/desktop/Window.cpp')
-rw-r--r--src/desktop/Window.cpp1879
1 files changed, 0 insertions, 1879 deletions
diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp
deleted file mode 100644
index 75dc7215..00000000
--- a/src/desktop/Window.cpp
+++ /dev/null
@@ -1,1879 +0,0 @@
-#include <algorithm>
-#include <ranges>
-#include <hyprutils/animation/AnimatedVariable.hpp>
-#include <re2/re2.h>
-
-#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
-#include <sys/types.h>
-#include <sys/sysctl.h>
-#endif
-
-#include <any>
-#include <bit>
-#include <string_view>
-#include "Window.hpp"
-#include "state/FocusState.hpp"
-#include "../Compositor.hpp"
-#include "../render/decorations/CHyprDropShadowDecoration.hpp"
-#include "../render/decorations/CHyprGroupBarDecoration.hpp"
-#include "../render/decorations/CHyprBorderDecoration.hpp"
-#include "../config/ConfigValue.hpp"
-#include "../config/ConfigManager.hpp"
-#include "../managers/TokenManager.hpp"
-#include "../managers/animation/AnimationManager.hpp"
-#include "../managers/ANRManager.hpp"
-#include "../managers/eventLoop/EventLoopManager.hpp"
-#include "../protocols/XDGShell.hpp"
-#include "../protocols/core/Compositor.hpp"
-#include "../protocols/core/Subcompositor.hpp"
-#include "../protocols/ContentType.hpp"
-#include "../protocols/FractionalScale.hpp"
-#include "../xwayland/XWayland.hpp"
-#include "../helpers/Color.hpp"
-#include "../helpers/math/Expression.hpp"
-#include "../events/Events.hpp"
-#include "../managers/XWaylandManager.hpp"
-#include "../render/Renderer.hpp"
-#include "../managers/LayoutManager.hpp"
-#include "../managers/HookSystemManager.hpp"
-#include "../managers/EventManager.hpp"
-#include "../managers/input/InputManager.hpp"
-
-#include <hyprutils/string/String.hpp>
-
-using namespace Hyprutils::String;
-using namespace Hyprutils::Animation;
-using enum NContentType::eContentType;
-
-PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
- PHLWINDOW pWindow = SP<CWindow>(new CWindow(surface));
-
- pWindow->m_self = pWindow;
- pWindow->m_isX11 = true;
- pWindow->m_ruleApplicator = makeUnique<Desktop::Rule::CWindowRuleApplicator>(pWindow);
-
- g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_realPosition, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
- g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_realSize, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
- g_pAnimationManager->createAnimation(0.f, pWindow->m_borderFadeAnimationProgress, g_pConfigManager->getAnimationPropertyConfig("border"), pWindow, AVARDAMAGE_BORDER);
- g_pAnimationManager->createAnimation(0.f, pWindow->m_borderAngleAnimationProgress, g_pConfigManager->getAnimationPropertyConfig("borderangle"), pWindow, AVARDAMAGE_BORDER);
- g_pAnimationManager->createAnimation(1.f, pWindow->m_alpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE);
- g_pAnimationManager->createAnimation(1.f, pWindow->m_activeInactiveAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE);
- g_pAnimationManager->createAnimation(CHyprColor(), pWindow->m_realShadowColor, g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW);
- g_pAnimationManager->createAnimation(0.f, pWindow->m_dimPercent, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE);
- g_pAnimationManager->createAnimation(0.f, pWindow->m_movingToWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE);
- g_pAnimationManager->createAnimation(0.f, pWindow->m_movingFromWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE);
- g_pAnimationManager->createAnimation(0.f, pWindow->m_notRespondingTint, g_pConfigManager->getAnimationPropertyConfig("fade"), pWindow, AVARDAMAGE_ENTIRE);
-
- pWindow->addWindowDeco(makeUnique<CHyprDropShadowDecoration>(pWindow));
- pWindow->addWindowDeco(makeUnique<CHyprBorderDecoration>(pWindow));
-
- return pWindow;
-}
-
-PHLWINDOW CWindow::create(SP<CXDGSurfaceResource> resource) {
- PHLWINDOW pWindow = SP<CWindow>(new CWindow(resource));
-
- pWindow->m_self = pWindow;
- resource->m_toplevel->m_window = pWindow;
- pWindow->m_ruleApplicator = makeUnique<Desktop::Rule::CWindowRuleApplicator>(pWindow);
-
- g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_realPosition, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
- g_pAnimationManager->createAnimation(Vector2D(0, 0), pWindow->m_realSize, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
- g_pAnimationManager->createAnimation(0.f, pWindow->m_borderFadeAnimationProgress, g_pConfigManager->getAnimationPropertyConfig("border"), pWindow, AVARDAMAGE_BORDER);
- g_pAnimationManager->createAnimation(0.f, pWindow->m_borderAngleAnimationProgress, g_pConfigManager->getAnimationPropertyConfig("borderangle"), pWindow, AVARDAMAGE_BORDER);
- g_pAnimationManager->createAnimation(1.f, pWindow->m_alpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE);
- g_pAnimationManager->createAnimation(1.f, pWindow->m_activeInactiveAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE);
- g_pAnimationManager->createAnimation(CHyprColor(), pWindow->m_realShadowColor, g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW);
- g_pAnimationManager->createAnimation(0.f, pWindow->m_dimPercent, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE);
- g_pAnimationManager->createAnimation(0.f, pWindow->m_movingToWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeOut"), pWindow, AVARDAMAGE_ENTIRE);
- g_pAnimationManager->createAnimation(0.f, pWindow->m_movingFromWorkspaceAlpha, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE);
- g_pAnimationManager->createAnimation(0.f, pWindow->m_notRespondingTint, g_pConfigManager->getAnimationPropertyConfig("fade"), pWindow, AVARDAMAGE_ENTIRE);
-
- pWindow->addWindowDeco(makeUnique<CHyprDropShadowDecoration>(pWindow));
- pWindow->addWindowDeco(makeUnique<CHyprBorderDecoration>(pWindow));
-
- pWindow->m_wlSurface->assign(pWindow->m_xdgSurface->m_surface.lock(), pWindow);
-
- return pWindow;
-}
-
-CWindow::CWindow(SP<CXDGSurfaceResource> resource) : m_xdgSurface(resource) {
- m_wlSurface = CWLSurface::create();
-
- m_listeners.map = m_xdgSurface->m_events.map.listen([this] { Events::listener_mapWindow(this, nullptr); });
- m_listeners.ack = m_xdgSurface->m_events.ack.listen([this](uint32_t d) { onAck(d); });
- m_listeners.unmap = m_xdgSurface->m_events.unmap.listen([this] { Events::listener_unmapWindow(this, nullptr); });
- m_listeners.destroy = m_xdgSurface->m_events.destroy.listen([this] { Events::listener_destroyWindow(this, nullptr); });
- m_listeners.commit = m_xdgSurface->m_events.commit.listen([this] { Events::listener_commitWindow(this, nullptr); });
- m_listeners.updateState = m_xdgSurface->m_toplevel->m_events.stateChanged.listen([this] { onUpdateState(); });
- m_listeners.updateMetadata = m_xdgSurface->m_toplevel->m_events.metadataChanged.listen([this] { onUpdateMeta(); });
-}
-
-CWindow::CWindow(SP<CXWaylandSurface> surface) : m_xwaylandSurface(surface) {
- m_wlSurface = CWLSurface::create();
-
- m_listeners.map = m_xwaylandSurface->m_events.map.listen([this] { Events::listener_mapWindow(this, nullptr); });
- m_listeners.unmap = m_xwaylandSurface->m_events.unmap.listen([this] { Events::listener_unmapWindow(this, nullptr); });
- m_listeners.destroy = m_xwaylandSurface->m_events.destroy.listen([this] { Events::listener_destroyWindow(this, nullptr); });
- m_listeners.commit = m_xwaylandSurface->m_events.commit.listen([this] { Events::listener_commitWindow(this, nullptr); });
- m_listeners.configureRequest = m_xwaylandSurface->m_events.configureRequest.listen([this](const CBox& box) { onX11ConfigureRequest(box); });
- m_listeners.updateState = m_xwaylandSurface->m_events.stateChanged.listen([this] { onUpdateState(); });
- m_listeners.updateMetadata = m_xwaylandSurface->m_events.metadataChanged.listen([this] { onUpdateMeta(); });
- m_listeners.resourceChange = m_xwaylandSurface->m_events.resourceChange.listen([this] { onResourceChangeX11(); });
- m_listeners.activate = m_xwaylandSurface->m_events.activate.listen([this] { Events::listener_activateX11(this, nullptr); });
-
- if (m_xwaylandSurface->m_overrideRedirect)
- m_listeners.setGeometry = m_xwaylandSurface->m_events.setGeometry.listen([this] { Events::listener_unmanagedSetGeometry(this, nullptr); });
-}
-
-CWindow::~CWindow() {
- if (Desktop::focusState()->window() == m_self) {
- Desktop::focusState()->surface().reset();
- Desktop::focusState()->window().reset();
- }
-
- m_events.destroy.emit();
-
- if (!g_pHyprOpenGL)
- return;
-
- g_pHyprRenderer->makeEGLCurrent();
- std::erase_if(g_pHyprOpenGL->m_windowFramebuffers, [&](const auto& other) { return other.first.expired() || other.first.get() == this; });
-}
-
-SBoxExtents CWindow::getFullWindowExtents() {
- if (m_fadingOut)
- return m_originalClosedExtents;
-
- const int BORDERSIZE = getRealBorderSize();
-
- if (m_ruleApplicator->dimAround().valueOrDefault()) {
- if (const auto PMONITOR = m_monitor.lock(); PMONITOR)
- return {.topLeft = {m_realPosition->value().x - PMONITOR->m_position.x, m_realPosition->value().y - PMONITOR->m_position.y},
- .bottomRight = {PMONITOR->m_size.x - (m_realPosition->value().x - PMONITOR->m_position.x),
- PMONITOR->m_size.y - (m_realPosition->value().y - PMONITOR->m_position.y)}};
- }
-
- SBoxExtents maxExtents = {.topLeft = {BORDERSIZE + 2, BORDERSIZE + 2}, .bottomRight = {BORDERSIZE + 2, BORDERSIZE + 2}};
-
- const auto EXTENTS = g_pDecorationPositioner->getWindowDecorationExtents(m_self);
-
- maxExtents.topLeft.x = std::max(EXTENTS.topLeft.x, maxExtents.topLeft.x);
-
- maxExtents.topLeft.y = std::max(EXTENTS.topLeft.y, maxExtents.topLeft.y);
-
- maxExtents.bottomRight.x = std::max(EXTENTS.bottomRight.x, maxExtents.bottomRight.x);
-
- maxExtents.bottomRight.y = std::max(EXTENTS.bottomRight.y, maxExtents.bottomRight.y);
-
- if (m_wlSurface->exists() && !m_isX11 && m_popupHead) {
- CBox surfaceExtents = {0, 0, 0, 0};
- // TODO: this could be better, perhaps make a getFullWindowRegion?
- m_popupHead->breadthfirst(
- [](WP<CPopup> popup, void* data) {
- if (!popup->m_wlSurface || !popup->m_wlSurface->resource())
- return;
-
- CBox* pSurfaceExtents = sc<CBox*>(data);
- CBox surf = CBox{popup->coordsRelativeToParent(), popup->size()};
- pSurfaceExtents->x = std::min(surf.x, pSurfaceExtents->x);
- pSurfaceExtents->y = std::min(surf.y, pSurfaceExtents->y);
- if (surf.x + surf.w > pSurfaceExtents->width)
- pSurfaceExtents->width = surf.x + surf.w - pSurfaceExtents->x;
- if (surf.y + surf.h > pSurfaceExtents->height)
- pSurfaceExtents->height = surf.y + surf.h - pSurfaceExtents->y;
- },
- &surfaceExtents);
-
- maxExtents.topLeft.x = std::max(-surfaceExtents.x, maxExtents.topLeft.x);
-
- maxExtents.topLeft.y = std::max(-surfaceExtents.y, maxExtents.topLeft.y);
-
- if (surfaceExtents.x + surfaceExtents.width > m_wlSurface->resource()->m_current.size.x + maxExtents.bottomRight.x)
- maxExtents.bottomRight.x = surfaceExtents.x + surfaceExtents.width - m_wlSurface->resource()->m_current.size.x;
-
- if (surfaceExtents.y + surfaceExtents.height > m_wlSurface->resource()->m_current.size.y + maxExtents.bottomRight.y)
- maxExtents.bottomRight.y = surfaceExtents.y + surfaceExtents.height - m_wlSurface->resource()->m_current.size.y;
- }
-
- return maxExtents;
-}
-
-CBox CWindow::getFullWindowBoundingBox() {
- if (m_ruleApplicator->dimAround().valueOrDefault()) {
- if (const auto PMONITOR = m_monitor.lock(); PMONITOR)
- return {PMONITOR->m_position.x, PMONITOR->m_position.y, PMONITOR->m_size.x, PMONITOR->m_size.y};
- }
-
- auto maxExtents = getFullWindowExtents();
-
- CBox finalBox = {m_realPosition->value().x - maxExtents.topLeft.x, m_realPosition->value().y - maxExtents.topLeft.y,
- m_realSize->value().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_realSize->value().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
-
- return finalBox;
-}
-
-CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
- const auto PMONITOR = m_monitor.lock();
-
- if (!PMONITOR)
- return {m_position, m_size};
-
- auto POS = m_position;
- auto SIZE = m_size;
-
- if (isFullscreen()) {
- POS = PMONITOR->m_position;
- SIZE = PMONITOR->m_size;
-
- return CBox{sc<int>(POS.x), sc<int>(POS.y), sc<int>(SIZE.x), sc<int>(SIZE.y)};
- }
-
- if (DELTALESSTHAN(POS.y - PMONITOR->m_position.y, PMONITOR->m_reservedArea.top(), 1)) {
- POS.y = PMONITOR->m_position.y;
- SIZE.y += PMONITOR->m_reservedArea.top();
- }
- if (DELTALESSTHAN(POS.x - PMONITOR->m_position.x, PMONITOR->m_reservedArea.left(), 1)) {
- POS.x = PMONITOR->m_position.x;
- SIZE.x += PMONITOR->m_reservedArea.left();
- }
- if (DELTALESSTHAN(POS.x + SIZE.x - PMONITOR->m_position.x, PMONITOR->m_size.x - PMONITOR->m_reservedArea.right(), 1)) {
- SIZE.x += PMONITOR->m_reservedArea.right();
- }
- if (DELTALESSTHAN(POS.y + SIZE.y - PMONITOR->m_position.y, PMONITOR->m_size.y - PMONITOR->m_reservedArea.bottom(), 1)) {
- SIZE.y += PMONITOR->m_reservedArea.bottom();
- }
-
- return CBox{sc<int>(POS.x), sc<int>(POS.y), sc<int>(SIZE.x), sc<int>(SIZE.y)};
-}
-
-SBoxExtents CWindow::getWindowExtentsUnified(uint64_t properties) {
- SBoxExtents extents = {.topLeft = {0, 0}, .bottomRight = {0, 0}};
- if (properties & RESERVED_EXTENTS)
- extents.addExtents(g_pDecorationPositioner->getWindowDecorationReserved(m_self));
- if (properties & INPUT_EXTENTS)
- extents.addExtents(g_pDecorationPositioner->getWindowDecorationExtents(m_self, true));
- if (properties & FULL_EXTENTS)
- extents.addExtents(g_pDecorationPositioner->getWindowDecorationExtents(m_self, false));
-
- return extents;
-}
-
-CBox CWindow::getWindowBoxUnified(uint64_t properties) {
- if (m_ruleApplicator->dimAround().valueOrDefault()) {
- const auto PMONITOR = m_monitor.lock();
- if (PMONITOR)
- return {PMONITOR->m_position.x, PMONITOR->m_position.y, PMONITOR->m_size.x, PMONITOR->m_size.y};
- }
-
- const auto POS = m_realPosition->value();
- const auto SIZE = m_realSize->value();
-
- CBox box{POS, SIZE};
- box.addExtents(getWindowExtentsUnified(properties));
-
- return box;
-}
-
-SBoxExtents CWindow::getFullWindowReservedArea() {
- return g_pDecorationPositioner->getWindowDecorationReserved(m_self);
-}
-
-void CWindow::updateWindowDecos() {
-
- if (!m_isMapped || isHidden())
- return;
-
- for (auto const& wd : m_decosToRemove) {
- for (auto it = m_windowDecorations.begin(); it != m_windowDecorations.end(); it++) {
- if (it->get() == wd) {
- g_pDecorationPositioner->uncacheDecoration(it->get());
- it = m_windowDecorations.erase(it);
- if (it == m_windowDecorations.end())
- break;
- }
- }
- }
-
- g_pDecorationPositioner->onWindowUpdate(m_self.lock());
-
- m_decosToRemove.clear();
-
- // make a copy because updateWindow can remove decos.
- std::vector<IHyprWindowDecoration*> decos;
- // reserve to avoid reallocations
- decos.reserve(m_windowDecorations.size());
-
- for (auto const& wd : m_windowDecorations) {
- decos.push_back(wd.get());
- }
-
- for (auto const& wd : decos) {
- if (std::ranges::find_if(m_windowDecorations, [wd](const auto& other) { return other.get() == wd; }) == m_windowDecorations.end())
- continue;
- wd->updateWindow(m_self.lock());
- }
-}
-
-void CWindow::addWindowDeco(UP<IHyprWindowDecoration> deco) {
- m_windowDecorations.emplace_back(std::move(deco));
- g_pDecorationPositioner->forceRecalcFor(m_self.lock());
- updateWindowDecos();
- g_pLayoutManager->getCurrentLayout()->recalculateWindow(m_self.lock());
-}
-
-void CWindow::removeWindowDeco(IHyprWindowDecoration* deco) {
- m_decosToRemove.push_back(deco);
- g_pDecorationPositioner->forceRecalcFor(m_self.lock());
- updateWindowDecos();
- g_pLayoutManager->getCurrentLayout()->recalculateWindow(m_self.lock());
-}
-
-void CWindow::uncacheWindowDecos() {
- for (auto const& wd : m_windowDecorations) {
- g_pDecorationPositioner->uncacheDecoration(wd.get());
- }
-}
-
-bool CWindow::checkInputOnDecos(const eInputType type, const Vector2D& mouseCoords, std::any data) {
- if (type != INPUT_TYPE_DRAG_END && hasPopupAt(mouseCoords))
- return false;
-
- for (auto const& wd : m_windowDecorations) {
- if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT))
- continue;
-
- if (!g_pDecorationPositioner->getWindowDecorationBox(wd.get()).containsPoint(mouseCoords))
- continue;
-
- if (wd->onInputOnDeco(type, mouseCoords, data))
- return true;
- }
-
- return false;
-}
-
-pid_t CWindow::getPID() {
- pid_t PID = -1;
- if (!m_isX11) {
- if (!m_xdgSurface || !m_xdgSurface->m_owner /* happens at unmap */)
- return -1;
-
- wl_client_get_credentials(m_xdgSurface->m_owner->client(), &PID, nullptr, nullptr);
- } else {
- if (!m_xwaylandSurface)
- return -1;
-
- PID = m_xwaylandSurface->m_pid;
- }
-
- return PID;
-}
-
-IHyprWindowDecoration* CWindow::getDecorationByType(eDecorationType type) {
- for (auto const& wd : m_windowDecorations) {
- if (wd->getDecorationType() == type)
- return wd.get();
- }
-
- return nullptr;
-}
-
-void CWindow::updateToplevel() {
- updateSurfaceScaleTransformDetails();
-}
-
-void CWindow::updateSurfaceScaleTransformDetails(bool force) {
- if (!m_isMapped || m_hidden || g_pCompositor->m_unsafeState)
- return;
-
- const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(m_lastSurfaceMonitorID);
-
- m_lastSurfaceMonitorID = monitorID();
-
- const auto PNEWMONITOR = m_monitor.lock();
-
- if (!PNEWMONITOR)
- return;
-
- if (PNEWMONITOR != PLASTMONITOR || force) {
- if (PLASTMONITOR && PLASTMONITOR->m_enabled && PNEWMONITOR != PLASTMONITOR)
- m_wlSurface->resource()->breadthfirst([PLASTMONITOR](SP<CWLSurfaceResource> s, const Vector2D& offset, void* d) { s->leave(PLASTMONITOR->m_self.lock()); }, nullptr);
-
- m_wlSurface->resource()->breadthfirst([PNEWMONITOR](SP<CWLSurfaceResource> s, const Vector2D& offset, void* d) { s->enter(PNEWMONITOR->m_self.lock()); }, nullptr);
- }
-
- const auto PMONITOR = m_monitor.lock();
-
- m_wlSurface->resource()->breadthfirst(
- [PMONITOR](SP<CWLSurfaceResource> s, const Vector2D& offset, void* d) {
- const auto PSURFACE = CWLSurface::fromResource(s);
- if (PSURFACE && PSURFACE->m_lastScaleFloat == PMONITOR->m_scale)
- return;
-
- PROTO::fractional->sendScale(s, PMONITOR->m_scale);
- g_pCompositor->setPreferredScaleForSurface(s, PMONITOR->m_scale);
- g_pCompositor->setPreferredTransformForSurface(s, PMONITOR->m_transform);
- },
- nullptr);
-}
-
-void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
- if (m_workspace == pWorkspace)
- return;
-
- static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking");
-
- if (!m_initialWorkspaceToken.empty()) {
- const auto TOKEN = g_pTokenManager->getToken(m_initialWorkspaceToken);
- if (TOKEN) {
- if (*PINITIALWSTRACKING == 2) {
- // persistent
- SInitialWorkspaceToken token = std::any_cast<SInitialWorkspaceToken>(TOKEN->m_data);
- if (token.primaryOwner == m_self) {
- token.workspace = pWorkspace->getConfigName();
- TOKEN->m_data = token;
- }
- }
- }
- }
-
- static auto PCLOSEONLASTSPECIAL = CConfigValue<Hyprlang::INT>("misc:close_special_on_empty");
-
- const auto OLDWORKSPACE = m_workspace;
-
- if (OLDWORKSPACE->isVisible()) {
- m_movingToWorkspaceAlpha->setValueAndWarp(1.F);
- *m_movingToWorkspaceAlpha = 0.F;
- m_movingToWorkspaceAlpha->setCallbackOnEnd([this](auto) { m_monitorMovedFrom = -1; });
- m_monitorMovedFrom = OLDWORKSPACE ? OLDWORKSPACE->monitorID() : -1;
- }
-
- m_workspace = pWorkspace;
-
- setAnimationsToMove();
-
- OLDWORKSPACE->updateWindows();
- OLDWORKSPACE->updateWindowData();
- g_pLayoutManager->getCurrentLayout()->recalculateMonitor(OLDWORKSPACE->monitorID());
-
- pWorkspace->updateWindows();
- pWorkspace->updateWindowData();
- g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
-
- g_pCompositor->updateAllWindowsAnimatedDecorationValues();
-
- if (valid(pWorkspace)) {
- g_pEventManager->postEvent(SHyprIPCEvent{.event = "movewindow", .data = std::format("{:x},{}", rc<uintptr_t>(this), pWorkspace->m_name)});
- g_pEventManager->postEvent(SHyprIPCEvent{.event = "movewindowv2", .data = std::format("{:x},{},{}", rc<uintptr_t>(this), pWorkspace->m_id, pWorkspace->m_name)});
- EMIT_HOOK_EVENT("moveWindow", (std::vector<std::any>{m_self.lock(), pWorkspace}));
- }
-
- if (const auto SWALLOWED = m_swallowed.lock()) {
- if (SWALLOWED->m_currentlySwallowed) {
- SWALLOWED->moveToWorkspace(pWorkspace);
- SWALLOWED->m_monitor = m_monitor;
- }
- }
-
- if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_id) && OLDWORKSPACE->getWindows() == 0 && *PCLOSEONLASTSPECIAL) {
- if (const auto PMONITOR = OLDWORKSPACE->m_monitor.lock(); PMONITOR)
- PMONITOR->setSpecialWorkspace(nullptr);
- }
-}
-
-PHLWINDOW CWindow::x11TransientFor() {
- if (!m_xwaylandSurface || !m_xwaylandSurface->m_parent)
- return nullptr;
-
- auto s = m_xwaylandSurface->m_parent;
- std::vector<SP<CXWaylandSurface>> visited;
- while (s) {
- // break loops. Some X apps make them, and it seems like it's valid behavior?!?!?!
- // TODO: we should reject loops being created in the first place.
- if (std::ranges::find(visited.begin(), visited.end(), s) != visited.end())
- break;
-
- visited.emplace_back(s.lock());
- s = s->m_parent;
- }
-
- if (s == m_xwaylandSurface)
- return nullptr; // dead-ass circle
-
- for (auto const& w : g_pCompositor->m_windows) {
- if (w->m_xwaylandSurface != s)
- continue;
- return w;
- }
-
- return nullptr;
-}
-
-void CWindow::onUnmap() {
- static auto PCLOSEONLASTSPECIAL = CConfigValue<Hyprlang::INT>("misc:close_special_on_empty");
- static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking");
-
- if (!m_initialWorkspaceToken.empty()) {
- const auto TOKEN = g_pTokenManager->getToken(m_initialWorkspaceToken);
- if (TOKEN) {
- if (*PINITIALWSTRACKING == 2) {
- // persistent token, but the first window got removed so the token is gone
- SInitialWorkspaceToken token = std::any_cast<SInitialWorkspaceToken>(TOKEN->m_data);
- if (token.primaryOwner == m_self)
- g_pTokenManager->removeToken(TOKEN);
- }
- }
- }
-
- m_lastWorkspace = m_workspace->m_id;
-
- // if the special workspace now has 0 windows, it will be closed, and this
- // window will no longer pass render checks, cuz the workspace will be nuked.
- // throw it into the main one for the fadeout.
- if (m_workspace->m_isSpecialWorkspace && m_workspace->getWindows() == 0)
- m_lastWorkspace = m_monitor->activeWorkspaceID();
-
- if (*PCLOSEONLASTSPECIAL && m_workspace && m_workspace->getWindows() == 0 && onSpecialWorkspace()) {
- const auto PMONITOR = m_monitor.lock();
- if (PMONITOR && PMONITOR->m_activeSpecialWorkspace && PMONITOR->m_activeSpecialWorkspace == m_workspace)
- PMONITOR->setSpecialWorkspace(nullptr);
- }
-
- const auto PMONITOR = m_monitor.lock();
-
- if (PMONITOR && PMONITOR->m_solitaryClient == m_self)
- PMONITOR->m_solitaryClient.reset();
-
- if (m_workspace) {
- m_workspace->updateWindows();
- m_workspace->updateWindowData();
- }
- g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
- g_pCompositor->updateAllWindowsAnimatedDecorationValues();
-
- m_workspace.reset();
-
- if (m_isX11)
- return;
-
- m_subsurfaceHead.reset();
- m_popupHead.reset();
-}
-
-void CWindow::onMap() {
- // JIC, reset the callbacks. If any are set, we'll make sure they are cleared so we don't accidentally unset them. (In case a window got remapped)
- m_realPosition->resetAllCallbacks();
- m_realSize->resetAllCallbacks();
- m_borderFadeAnimationProgress->resetAllCallbacks();
- m_borderAngleAnimationProgress->resetAllCallbacks();
- m_activeInactiveAlpha->resetAllCallbacks();
- m_alpha->resetAllCallbacks();
- m_realShadowColor->resetAllCallbacks();
- m_dimPercent->resetAllCallbacks();
- m_movingToWorkspaceAlpha->resetAllCallbacks();
- m_movingFromWorkspaceAlpha->resetAllCallbacks();
-
- m_movingFromWorkspaceAlpha->setValueAndWarp(1.F);
-
- if (m_borderAngleAnimationProgress->enabled()) {
- m_borderAngleAnimationProgress->setValueAndWarp(0.f);
- m_borderAngleAnimationProgress->setCallbackOnEnd([&](WP<CBaseAnimatedVariable> p) { onBorderAngleAnimEnd(p); }, false);
- *m_borderAngleAnimationProgress = 1.f;
- }
-
- m_realSize->setCallbackOnBegin(
- [this](auto) {
- if (!m_isMapped || isX11OverrideRedirect())
- return;
-
- g_pEventLoopManager->doLater([this, self = m_self] {
- if (!self)
- return;
-
- sendWindowSize();
- });
- },
- false);
-
- m_movingFromWorkspaceAlpha->setValueAndWarp(1.F);
-
- m_reportedSize = m_pendingReportedSize;
- m_animatingIn = true;
-
- updateSurfaceScaleTransformDetails(true);
-
- if (m_isX11)
- return;
-
- m_subsurfaceHead = CSubsurface::create(m_self.lock());
- m_popupHead = CPopup::create(m_self.lock());
-}
-
-void CWindow::onBorderAngleAnimEnd(WP<CBaseAnimatedVariable> pav) {
- const auto PAV = pav.lock();
- if (!PAV)
- return;
-
- if (PAV->getStyle() != "loop" || !PAV->enabled())
- return;
-
- const auto PANIMVAR = dc<CAnimatedVariable<float>*>(PAV.get());
-
- PANIMVAR->setCallbackOnEnd(nullptr); // we remove the callback here because otherwise setvalueandwarp will recurse this
-
- PANIMVAR->setValueAndWarp(0);
- *PANIMVAR = 1.f;
-
- PANIMVAR->setCallbackOnEnd([&](WP<CBaseAnimatedVariable> pav) { onBorderAngleAnimEnd(pav); }, false);
-}
-
-void CWindow::setHidden(bool hidden) {
- m_hidden = hidden;
-
- if (hidden && Desktop::focusState()->window() == m_self)
- Desktop::focusState()->window().reset();
-
- setSuspended(hidden);
-}
-
-bool CWindow::isHidden() {
- return m_hidden;
-}
-
-// check if the point is "hidden" under a rounded corner of the window
-// it is assumed that the point is within the real window box (m_vRealPosition, m_vRealSize)
-// otherwise behaviour is undefined
-bool CWindow::isInCurvedCorner(double x, double y) {
- const int ROUNDING = rounding();
- const int ROUNDINGPOWER = roundingPower();
- if (getRealBorderSize() >= ROUNDING)
- return false;
-
- // (x0, y0), (x0, y1), ... are the center point of rounding at each corner
- double x0 = m_realPosition->value().x + ROUNDING;
- double y0 = m_realPosition->value().y + ROUNDING;
- double x1 = m_realPosition->value().x + m_realSize->value().x - ROUNDING;
- double y1 = m_realPosition->value().y + m_realSize->value().y - ROUNDING;
-
- if (x < x0 && y < y0) {
- return std::pow(x0 - x, ROUNDINGPOWER) + std::pow(y0 - y, ROUNDINGPOWER) > std::pow(sc<double>(ROUNDING), ROUNDINGPOWER);
- }
- if (x > x1 && y < y0) {
- return std::pow(x - x1, ROUNDINGPOWER) + std::pow(y0 - y, ROUNDINGPOWER) > std::pow(sc<double>(ROUNDING), ROUNDINGPOWER);
- }
- if (x < x0 && y > y1) {
- return std::pow(x0 - x, ROUNDINGPOWER) + std::pow(y - y1, ROUNDINGPOWER) > std::pow(sc<double>(ROUNDING), ROUNDINGPOWER);
- }
- if (x > x1 && y > y1) {
- return std::pow(x - x1, ROUNDINGPOWER) + std::pow(y - y1, ROUNDINGPOWER) > std::pow(sc<double>(ROUNDING), ROUNDINGPOWER);
- }
-
- return false;
-}
-
-// checks if the wayland window has a popup at pos
-bool CWindow::hasPopupAt(const Vector2D& pos) {
- if (m_isX11)
- return false;
-
- auto popup = m_popupHead->at(pos);
-
- return popup && popup->m_wlSurface->resource();
-}
-
-void CWindow::applyGroupRules() {
- if ((m_groupRules & GROUP_SET && m_firstMap) || m_groupRules & GROUP_SET_ALWAYS)
- createGroup();
-
- if (m_groupData.pNextWindow.lock() && ((m_groupRules & GROUP_LOCK && m_firstMap) || m_groupRules & GROUP_LOCK_ALWAYS))
- getGroupHead()->m_groupData.locked = true;
-}
-
-void CWindow::createGroup() {
- if (m_groupData.deny) {
- Debug::log(LOG, "createGroup: window:{:x},title:{} is denied as a group, ignored", rc<uintptr_t>(this), this->m_title);
- return;
- }
-
- if (m_groupData.pNextWindow.expired()) {
- m_groupData.pNextWindow = m_self;
- m_groupData.head = true;
- m_groupData.locked = false;
- m_groupData.deny = false;
-
- addWindowDeco(makeUnique<CHyprGroupBarDecoration>(m_self.lock()));
-
- if (m_workspace) {
- m_workspace->updateWindows();
- m_workspace->updateWindowData();
- }
- g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
- g_pCompositor->updateAllWindowsAnimatedDecorationValues();
-
- g_pEventManager->postEvent(SHyprIPCEvent{.event = "togglegroup", .data = std::format("1,{:x}", rc<uintptr_t>(this))});
- }
-
- m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
-}
-
-void CWindow::destroyGroup() {
- if (m_groupData.pNextWindow == m_self) {
- if (m_groupRules & GROUP_SET_ALWAYS) {
- Debug::log(LOG, "destoryGroup: window:{:x},title:{} has rule [group set always], ignored", rc<uintptr_t>(this), this->m_title);
- return;
- }
- m_groupData.pNextWindow.reset();
- m_groupData.head = false;
- updateWindowDecos();
- if (m_workspace) {
- m_workspace->updateWindows();
- m_workspace->updateWindowData();
- }
- g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
- g_pCompositor->updateAllWindowsAnimatedDecorationValues();
-
- g_pEventManager->postEvent(SHyprIPCEvent{.event = "togglegroup", .data = std::format("0,{:x}", rc<uintptr_t>(this))});
- m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
- return;
- }
-
- std::string addresses;
- PHLWINDOW curr = m_self.lock();
- std::vector<PHLWINDOW> members;
- do {
- const auto PLASTWIN = curr;
- curr = curr->m_groupData.pNextWindow.lock();
- PLASTWIN->m_groupData.pNextWindow.reset();
- curr->setHidden(false);
- members.push_back(curr);
-
- addresses += std::format("{:x},", rc<uintptr_t>(curr.get()));
- } while (curr.get() != this);
-
- for (auto const& w : members) {
- if (w->m_groupData.head)
- g_pLayoutManager->getCurrentLayout()->onWindowRemoved(curr);
- w->m_groupData.head = false;
- }
-
- const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_groupsLocked;
- g_pKeybindManager->m_groupsLocked = true;
- for (auto const& w : members) {
- g_pLayoutManager->getCurrentLayout()->onWindowCreated(w);
- w->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
- w->updateWindowDecos();
- }
- g_pKeybindManager->m_groupsLocked = GROUPSLOCKEDPREV;
-
- if (m_workspace) {
- m_workspace->updateWindows();
- m_workspace->updateWindowData();
- }
- g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
- g_pCompositor->updateAllWindowsAnimatedDecorationValues();
-
- if (!addresses.empty())
- addresses.pop_back();
-
- m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
- g_pEventManager->postEvent(SHyprIPCEvent{.event = "togglegroup", .data = std::format("0,{}", addresses)});
-}
-
-PHLWINDOW CWindow::getGroupHead() {
- PHLWINDOW curr = m_self.lock();
- while (!curr->m_groupData.head)
- curr = curr->m_groupData.pNextWindow.lock();
- return curr;
-}
-
-PHLWINDOW CWindow::getGroupTail() {
- PHLWINDOW curr = m_self.lock();
- while (!curr->m_groupData.pNextWindow->m_groupData.head)
- curr = curr->m_groupData.pNextWindow.lock();
- return curr;
-}
-
-PHLWINDOW CWindow::getGroupCurrent() {
- PHLWINDOW curr = m_self.lock();
- while (curr->isHidden())
- curr = curr->m_groupData.pNextWindow.lock();
- return curr;
-}
-
-int CWindow::getGroupSize() {
- int size = 1;
- PHLWINDOW curr = m_self.lock();
- while (curr->m_groupData.pNextWindow != m_self) {
- curr = curr->m_groupData.pNextWindow.lock();
- size++;
- }
- return size;
-}
-
-bool CWindow::canBeGroupedInto(PHLWINDOW pWindow) {
- static auto ALLOWGROUPMERGE = CConfigValue<Hyprlang::INT>("group:merge_groups_on_drag");
- bool isGroup = m_groupData.pNextWindow;
- bool disallowDragIntoGroup = g_pInputManager->m_wasDraggingWindow && isGroup && !sc<bool>(*ALLOWGROUPMERGE);
- return !g_pKeybindManager->m_groupsLocked // global group lock disengaged
- && ((m_groupRules & GROUP_INVADE && m_firstMap) // window ignore local group locks, or
- || (!pWindow->getGroupHead()->m_groupData.locked // target unlocked
- && !(m_groupData.pNextWindow.lock() && getGroupHead()->m_groupData.locked))) // source unlocked or isn't group
- && !m_groupData.deny // source is not denied entry
- && !(m_groupRules & GROUP_BARRED && m_firstMap) // group rule doesn't prevent adding window
- && !disallowDragIntoGroup; // config allows groups to be merged
-}
-
-PHLWINDOW CWindow::getGroupWindowByIndex(int index) {
- const int SIZE = getGroupSize();
- index = ((index % SIZE) + SIZE) % SIZE;
- PHLWINDOW curr = getGroupHead();
- while (index > 0) {
- curr = curr->m_groupData.pNextWindow.lock();
- index--;
- }
- return curr;
-}
-
-bool CWindow::hasInGroup(PHLWINDOW w) {
- PHLWINDOW curr = m_groupData.pNextWindow.lock();
- while (curr && curr != m_self) {
- if (curr == w)
- return true;
- curr = curr->m_groupData.pNextWindow.lock();
- }
- return false;
-}
-
-void CWindow::setGroupCurrent(PHLWINDOW pWindow) {
- PHLWINDOW curr = m_groupData.pNextWindow.lock();
- bool isMember = false;
- while (curr.get() != this) {
- if (curr == pWindow) {
- isMember = true;
- break;
- }
- curr = curr->m_groupData.pNextWindow.lock();
- }
-
- if (!isMember && pWindow.get() != this)
- return;
-
- const auto PCURRENT = getGroupCurrent();
- const bool FULLSCREEN = PCURRENT->isFullscreen();
- const auto WORKSPACE = PCURRENT->m_workspace;
- const auto MODE = PCURRENT->m_fullscreenState.internal;
-
- const auto CURRENTISFOCUS = PCURRENT == Desktop::focusState()->window();
-
- const auto PWINDOWSIZE = PCURRENT->m_realSize->value();
- const auto PWINDOWPOS = PCURRENT->m_realPosition->value();
- const auto PWINDOWSIZEGOAL = PCURRENT->m_realSize->goal();
- const auto PWINDOWPOSGOAL = PCURRENT->m_realPosition->goal();
- const auto PWINDOWLASTFLOATINGSIZE = PCURRENT->m_lastFloatingSize;
- const auto PWINDOWLASTFLOATINGPOSITION = PCURRENT->m_lastFloatingPosition;
-
- if (FULLSCREEN)
- g_pCompositor->setWindowFullscreenInternal(PCURRENT, FSMODE_NONE);
-
- PCURRENT->setHidden(true);
- pWindow->setHidden(false); // can remove m_pLastWindow
-
- g_pLayoutManager->getCurrentLayout()->replaceWindowDataWith(PCURRENT, pWindow);
-
- if (PCURRENT->m_isFloating) {
- pWindow->m_realPosition->setValueAndWarp(PWINDOWPOSGOAL);
- pWindow->m_realSize->setValueAndWarp(PWINDOWSIZEGOAL);
- pWindow->sendWindowSize();
- }
-
- pWindow->m_realPosition->setValue(PWINDOWPOS);
- pWindow->m_realSize->setValue(PWINDOWSIZE);
-
- if (FULLSCREEN)
- g_pCompositor->setWindowFullscreenInternal(pWindow, MODE);
-
- pWindow->m_lastFloatingSize = PWINDOWLASTFLOATINGSIZE;
- pWindow->m_lastFloatingPosition = PWINDOWLASTFLOATINGPOSITION;
-
- g_pCompositor->updateAllWindowsAnimatedDecorationValues();
-
- if (CURRENTISFOCUS)
- Desktop::focusState()->rawWindowFocus(pWindow);
-
- g_pHyprRenderer->damageWindow(pWindow);
-
- pWindow->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
- m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
- pWindow->updateWindowDecos();
-}
-
-void CWindow::insertWindowToGroup(PHLWINDOW pWindow) {
- const auto BEGINAT = m_self.lock();
- const auto ENDAT = m_groupData.pNextWindow.lock();
-
- if (!pWindow->m_groupData.pNextWindow.lock()) {
- BEGINAT->m_groupData.pNextWindow = pWindow;
- pWindow->m_groupData.pNextWindow = ENDAT;
- pWindow->m_groupData.head = false;
- pWindow->addWindowDeco(makeUnique<CHyprGroupBarDecoration>(pWindow));
- return;
- }
-
- const auto SHEAD = pWindow->getGroupHead();
- const auto STAIL = pWindow->getGroupTail();
-
- SHEAD->m_groupData.head = false;
- BEGINAT->m_groupData.pNextWindow = SHEAD;
- STAIL->m_groupData.pNextWindow = ENDAT;
-
- pWindow->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
- m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
- pWindow->updateWindowDecos();
-}
-
-PHLWINDOW CWindow::getGroupPrevious() {
- PHLWINDOW curr = m_groupData.pNextWindow.lock();
-
- while (curr != m_self && curr->m_groupData.pNextWindow != m_self)
- curr = curr->m_groupData.pNextWindow.lock();
-
- return curr;
-}
-
-void CWindow::switchWithWindowInGroup(PHLWINDOW pWindow) {
- if (!m_groupData.pNextWindow.lock() || !pWindow->m_groupData.pNextWindow.lock())
- return;
-
- if (m_groupData.pNextWindow.lock() == pWindow) { // A -> this -> pWindow -> B >> A -> pWindow -> this -> B
- getGroupPrevious()->m_groupData.pNextWindow = pWindow;
- m_groupData.pNextWindow = pWindow->m_groupData.pNextWindow;
- pWindow->m_groupData.pNextWindow = m_self;
-
- } else if (pWindow->m_groupData.pNextWindow == m_self) { // A -> pWindow -> this -> B >> A -> this -> pWindow -> B
- pWindow->getGroupPrevious()->m_groupData.pNextWindow = m_self;
- pWindow->m_groupData.pNextWindow = m_groupData.pNextWindow;
- m_groupData.pNextWindow = pWindow;
-
- } else { // A -> this -> B | C -> pWindow -> D >> A -> pWindow -> B | C -> this -> D
- std::swap(m_groupData.pNextWindow, pWindow->m_groupData.pNextWindow);
- std::swap(getGroupPrevious()->m_groupData.pNextWindow, pWindow->getGroupPrevious()->m_groupData.pNextWindow);
- }
-
- std::swap(m_groupData.head, pWindow->m_groupData.head);
- std::swap(m_groupData.locked, pWindow->m_groupData.locked);
-
- pWindow->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
- m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
- pWindow->updateWindowDecos();
-}
-
-void CWindow::updateGroupOutputs() {
- if (m_groupData.pNextWindow.expired())
- return;
-
- PHLWINDOW curr = m_groupData.pNextWindow.lock();
-
- const auto WS = m_workspace;
-
- while (curr.get() != this) {
- curr->m_monitor = m_monitor;
- curr->moveToWorkspace(WS);
-
- *curr->m_realPosition = m_realPosition->goal();
- *curr->m_realSize = m_realSize->goal();
-
- curr = curr->m_groupData.pNextWindow.lock();
- }
-}
-
-Vector2D CWindow::middle() {
- return m_realPosition->goal() + m_realSize->goal() / 2.f;
-}
-
-bool CWindow::opaque() {
- if (m_alpha->value() != 1.f || m_activeInactiveAlpha->value() != 1.f)
- return false;
-
- const auto PWORKSPACE = m_workspace;
-
- if (m_wlSurface->small() && !m_wlSurface->m_fillIgnoreSmall)
- return false;
-
- if (PWORKSPACE && PWORKSPACE->m_alpha->value() != 1.f)
- return false;
-
- if (m_isX11 && m_xwaylandSurface && m_xwaylandSurface->m_surface && m_xwaylandSurface->m_surface->m_current.texture)
- return m_xwaylandSurface->m_surface->m_current.texture->m_opaque;
-
- auto solitaryResource = getSolitaryResource();
- if (!solitaryResource || !solitaryResource->m_current.texture)
- return false;
-
- // TODO: this is wrong
- const auto EXTENTS = m_xdgSurface->m_surface->m_current.opaque.getExtents();
- if (EXTENTS.w >= m_xdgSurface->m_surface->m_current.bufferSize.x && EXTENTS.h >= m_xdgSurface->m_surface->m_current.bufferSize.y)
- return true;
-
- return solitaryResource->m_current.texture->m_opaque;
-}
-
-float CWindow::rounding() {
- static auto PROUNDING = CConfigValue<Hyprlang::INT>("decoration:rounding");
- static auto PROUNDINGPOWER = CConfigValue<Hyprlang::FLOAT>("decoration:rounding_power");
-
- float roundingPower = m_ruleApplicator->roundingPower().valueOr(*PROUNDINGPOWER);
- float rounding = m_ruleApplicator->rounding().valueOr(*PROUNDING) * (roundingPower / 2.0); /* Make perceived roundness consistent. */
-
- return rounding;
-}
-
-float CWindow::roundingPower() {
- static auto PROUNDINGPOWER = CConfigValue<Hyprlang::FLOAT>("decoration:rounding_power");
-
- return m_ruleApplicator->roundingPower().valueOr(std::clamp(*PROUNDINGPOWER, 1.F, 10.F));
-}
-
-void CWindow::updateWindowData() {
- const auto PWORKSPACE = m_workspace;
- const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{};
- updateWindowData(WORKSPACERULE);
-}
-
-void CWindow::updateWindowData(const SWorkspaceRule& workspaceRule) {
- m_ruleApplicator->borderSize().matchOptional(workspaceRule.borderSize, Desktop::Types::PRIORITY_WORKSPACE_RULE);
- m_ruleApplicator->decorate().matchOptional(workspaceRule.decorate, Desktop::Types::PRIORITY_WORKSPACE_RULE);
- m_ruleApplicator->borderSize().matchOptional(workspaceRule.noBorder ? std::optional<Hyprlang::INT>(0) : std::nullopt, Desktop::Types::PRIORITY_WORKSPACE_RULE);
- m_ruleApplicator->rounding().matchOptional(workspaceRule.noRounding.value_or(false) ? std::optional<Hyprlang::INT>(0) : std::nullopt, Desktop::Types::PRIORITY_WORKSPACE_RULE);
- m_ruleApplicator->noShadow().matchOptional(workspaceRule.noShadow, Desktop::Types::PRIORITY_WORKSPACE_RULE);
-}
-
-int CWindow::getRealBorderSize() {
- if ((m_workspace && isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) || !m_ruleApplicator->decorate().valueOrDefault())
- return 0;
-
- static auto PBORDERSIZE = CConfigValue<Hyprlang::INT>("general:border_size");
-
- return m_ruleApplicator->borderSize().valueOr(*PBORDERSIZE);
-}
-
-float CWindow::getScrollMouse() {
- static auto PINPUTSCROLLFACTOR = CConfigValue<Hyprlang::FLOAT>("input:scroll_factor");
- return m_ruleApplicator->scrollMouse().valueOr(*PINPUTSCROLLFACTOR);
-}
-
-float CWindow::getScrollTouchpad() {
- static auto PTOUCHPADSCROLLFACTOR = CConfigValue<Hyprlang::FLOAT>("input:touchpad:scroll_factor");
- return m_ruleApplicator->scrollTouchpad().valueOr(*PTOUCHPADSCROLLFACTOR);
-}
-
-bool CWindow::isScrollMouseOverridden() {
- return m_ruleApplicator->scrollMouse().hasValue();
-}
-
-bool CWindow::isScrollTouchpadOverridden() {
- return m_ruleApplicator->scrollTouchpad().hasValue();
-}
-
-bool CWindow::canBeTorn() {
- static auto PTEARING = CConfigValue<Hyprlang::INT>("general:allow_tearing");
- return m_ruleApplicator->tearing().valueOr(m_tearingHint) && *PTEARING;
-}
-
-void CWindow::setSuspended(bool suspend) {
- if (suspend == m_suspended)
- return;
-
- if (m_isX11 || !m_xdgSurface || !m_xdgSurface->m_toplevel)
- return;
-
- m_xdgSurface->m_toplevel->setSuspeneded(suspend);
- m_suspended = suspend;
-}
-
-bool CWindow::visibleOnMonitor(PHLMONITOR pMonitor) {
- CBox wbox = {m_realPosition->value(), m_realSize->value()};
-
- if (m_isFloating)
- wbox = getFullWindowBoundingBox();
-
- return !wbox.intersection({pMonitor->m_position, pMonitor->m_size}).empty();
-}
-
-void CWindow::setAnimationsToMove() {
- m_realPosition->setConfig(g_pConfigManager->getAnimationPropertyConfig("windowsMove"));
- m_animatingIn = false;
-}
-
-void CWindow::onWorkspaceAnimUpdate() {
- // clip box for animated offsets
- if (!m_isFloating || m_pinned || isFullscreen() || m_draggingTiled) {
- m_floatingOffset = Vector2D(0, 0);
- return;
- }
-
- Vector2D offset;
- const auto PWORKSPACE = m_workspace;
- if (!PWORKSPACE)
- return;
-
- const auto PWSMON = m_monitor.lock();
- if (!PWSMON)
- return;
-
- const auto WINBB = getFullWindowBoundingBox();
- if (PWORKSPACE->m_renderOffset->value().x != 0) {
- const auto PROGRESS = PWORKSPACE->m_renderOffset->value().x / PWSMON->m_size.x;
-
- if (WINBB.x < PWSMON->m_position.x)
- offset.x += (PWSMON->m_position.x - WINBB.x) * PROGRESS;
-
- if (WINBB.x + WINBB.width > PWSMON->m_position.x + PWSMON->m_size.x)
- offset.x += (WINBB.x + WINBB.width - PWSMON->m_position.x - PWSMON->m_size.x) * PROGRESS;
- } else if (PWORKSPACE->m_renderOffset->value().y != 0) {
- const auto PROGRESS = PWORKSPACE->m_renderOffset->value().y / PWSMON->m_size.y;
-
- if (WINBB.y < PWSMON->m_position.y)
- offset.y += (PWSMON->m_position.y - WINBB.y) * PROGRESS;
-
- if (WINBB.y + WINBB.height > PWSMON->m_position.y + PWSMON->m_size.y)
- offset.y += (WINBB.y + WINBB.height - PWSMON->m_position.y - PWSMON->m_size.y) * PROGRESS;
- }
-
- m_floatingOffset = offset;
-}
-
-void CWindow::onFocusAnimUpdate() {
- // borderangle once
- if (m_borderAngleAnimationProgress->enabled() && !m_borderAngleAnimationProgress->isBeingAnimated()) {
- m_borderAngleAnimationProgress->setValueAndWarp(0.f);
- *m_borderAngleAnimationProgress = 1.f;
- }
-}
-
-int CWindow::popupsCount() {
- if (m_isX11 || !m_popupHead)
- return 0;
-
- int no = -1;
- m_popupHead->breadthfirst([](WP<CPopup> p, void* d) { *sc<int*>(d) += 1; }, &no);
- return no;
-}
-
-int CWindow::surfacesCount() {
- if (m_isX11)
- return 1;
-
- int no = 0;
- m_wlSurface->resource()->breadthfirst([](SP<CWLSurfaceResource> r, const Vector2D& offset, void* d) { *sc<int*>(d) += 1; }, &no);
- return no;
-}
-
-void CWindow::clampWindowSize(const std::optional<Vector2D> minSize, const std::optional<Vector2D> maxSize) {
- const Vector2D REALSIZE = m_realSize->goal();
- const Vector2D MAX = isFullscreen() ? Vector2D{INFINITY, INFINITY} : maxSize.value_or(Vector2D{INFINITY, INFINITY});
- const Vector2D NEWSIZE = REALSIZE.clamp(minSize.value_or(Vector2D{MIN_WINDOW_SIZE, MIN_WINDOW_SIZE}), MAX);
- const Vector2D DELTA = REALSIZE - NEWSIZE;
-
- *m_realPosition = m_realPosition->goal() + DELTA / 2.0;
- *m_realSize = NEWSIZE;
-}
-
-bool CWindow::isFullscreen() {
- return m_fullscreenState.internal != FSMODE_NONE;
-}
-
-bool CWindow::isEffectiveInternalFSMode(const eFullscreenMode MODE) {
- return sc<eFullscreenMode>(std::bit_floor(sc<uint8_t>(m_fullscreenState.internal))) == MODE;
-}
-
-WORKSPACEID CWindow::workspaceID() {
- return m_workspace ? m_workspace->m_id : m_lastWorkspace;
-}
-
-MONITORID CWindow::monitorID() {
- return m_monitor ? m_monitor->m_id : MONITOR_INVALID;
-}
-
-bool CWindow::onSpecialWorkspace() {
- return m_workspace ? m_workspace->m_isSpecialWorkspace : g_pCompositor->isWorkspaceSpecial(m_lastWorkspace);
-}
-
-std::unordered_map<std::string, std::string> CWindow::getEnv() {
-
- const auto PID = getPID();
-
- if (PID <= 1)
- return {};
-
- std::unordered_map<std::string, std::string> results;
-
- std::vector<char> buffer;
- size_t needle = 0;
-
-#if defined(__linux__)
- //
- std::string environFile = "/proc/" + std::to_string(PID) + "/environ";
- std::ifstream ifs(environFile, std::ios::binary);
-
- if (!ifs.good())
- return {};
-
- buffer.resize(512, '\0');
- while (ifs.read(buffer.data() + needle, 512)) {
- buffer.resize(buffer.size() + 512, '\0');
- needle += 512;
- }
-#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
- int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ENV, static_cast<int>(PID)};
- size_t len = 0;
-
- if (sysctl(mib, 4, nullptr, &len, nullptr, 0) < 0 || len == 0)
- return {};
-
- buffer.resize(len, '\0');
-
- if (sysctl(mib, 4, buffer.data(), &len, nullptr, 0) < 0)
- return {};
-
- needle = len;
-#endif
-
- if (needle <= 1)
- return {};
-
- std::replace(buffer.begin(), buffer.end() - 1, '\0', '\n');
-
- CVarList envs(std::string{buffer.data(), buffer.size() - 1}, 0, '\n', true);
-
- for (auto const& e : envs) {
- if (!e.contains('='))
- continue;
-
- const auto EQ = e.find_first_of('=');
- results[e.substr(0, EQ)] = e.substr(EQ + 1);
- }
-
- return results;
-}
-
-void CWindow::activate(bool force) {
- if (Desktop::focusState()->window() == m_self)
- return;
-
- static auto PFOCUSONACTIVATE = CConfigValue<Hyprlang::INT>("misc:focus_on_activate");
-
- m_isUrgent = true;
-
- g_pEventManager->postEvent(SHyprIPCEvent{.event = "urgent", .data = std::format("{:x}", rc<uintptr_t>(this))});
- EMIT_HOOK_EVENT("urgent", m_self.lock());
-
- if (!force &&
- (!m_ruleApplicator->focusOnActivate().valueOr(*PFOCUSONACTIVATE) || (m_suppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY) || (m_suppressedEvents & SUPPRESS_ACTIVATE)))
- return;
-
- if (!m_isMapped) {
- Debug::log(LOG, "Ignoring CWindow::activate focus/warp, window is not mapped yet.");
- return;
- }
-
- if (m_isFloating)
- g_pCompositor->changeWindowZOrder(m_self.lock(), true);
-
- Desktop::focusState()->fullWindowFocus(m_self.lock());
- warpCursor();
-}
-
-void CWindow::onUpdateState() {
- std::optional<bool> requestsFS = m_xdgSurface ? m_xdgSurface->m_toplevel->m_state.requestsFullscreen : m_xwaylandSurface->m_state.requestsFullscreen;
- std::optional<MONITORID> requestsID = m_xdgSurface ? m_xdgSurface->m_toplevel->m_state.requestsFullscreenMonitor : MONITOR_INVALID;
- std::optional<bool> requestsMX = m_xdgSurface ? m_xdgSurface->m_toplevel->m_state.requestsMaximize : m_xwaylandSurface->m_state.requestsMaximize;
-
- if (requestsFS.has_value() && !(m_suppressedEvents & SUPPRESS_FULLSCREEN)) {
- if (requestsID.has_value() && (requestsID.value() != MONITOR_INVALID) && !(m_suppressedEvents & SUPPRESS_FULLSCREEN_OUTPUT)) {
- if (m_isMapped) {
- const auto monitor = g_pCompositor->getMonitorFromID(requestsID.value());
- g_pCompositor->moveWindowToWorkspaceSafe(m_self.lock(), monitor->m_activeWorkspace);
- Desktop::focusState()->rawMonitorFocus(monitor);
- }
-
- if (!m_isMapped)
- m_wantsInitialFullscreenMonitor = requestsID.value();
- }
-
- bool fs = requestsFS.value();
- if (m_isMapped)
- g_pCompositor->changeWindowFullscreenModeClient(m_self.lock(), FSMODE_FULLSCREEN, requestsFS.value());
-
- if (!m_isMapped)
- m_wantsInitialFullscreen = fs;
- }
-
- if (requestsMX.has_value() && !(m_suppressedEvents & SUPPRESS_MAXIMIZE)) {
- if (m_isMapped) {
- auto window = m_self.lock();
- auto state = sc<int8_t>(window->m_fullscreenState.client);
- bool maximized = (state & sc<uint8_t>(FSMODE_MAXIMIZED)) != 0;
- g_pCompositor->changeWindowFullscreenModeClient(window, FSMODE_MAXIMIZED, !maximized);
- }
- }
-}
-
-void CWindow::onUpdateMeta() {
- const auto NEWTITLE = fetchTitle();
- bool doUpdate = false;
-
- if (m_title != NEWTITLE) {
- m_title = NEWTITLE;
- g_pEventManager->postEvent(SHyprIPCEvent{.event = "windowtitle", .data = std::format("{:x}", rc<uintptr_t>(this))});
- g_pEventManager->postEvent(SHyprIPCEvent{.event = "windowtitlev2", .data = std::format("{:x},{}", rc<uintptr_t>(this), m_title)});
- EMIT_HOOK_EVENT("windowTitle", m_self.lock());
-
- if (m_self == Desktop::focusState()->window()) { // if it's the active, let's post an event to update others
- g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindow", .data = m_class + "," + m_title});
- g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindowv2", .data = std::format("{:x}", rc<uintptr_t>(this))});
- EMIT_HOOK_EVENT("activeWindow", m_self.lock());
- }
-
- Debug::log(LOG, "Window {:x} set title to {}", rc<uintptr_t>(this), m_title);
- doUpdate = true;
- }
-
- const auto NEWCLASS = fetchClass();
- if (m_class != NEWCLASS) {
- m_class = NEWCLASS;
-
- if (m_self == Desktop::focusState()->window()) { // if it's the active, let's post an event to update others
- g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindow", .data = m_class + "," + m_title});
- g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindowv2", .data = std::format("{:x}", rc<uintptr_t>(this))});
- EMIT_HOOK_EVENT("activeWindow", m_self.lock());
- }
-
- Debug::log(LOG, "Window {:x} set class to {}", rc<uintptr_t>(this), m_class);
- doUpdate = true;
- }
-
- if (doUpdate) {
- m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_TITLE | Desktop::Rule::RULE_PROP_CLASS);
- updateToplevel();
- }
-}
-
-std::string CWindow::fetchTitle() {
- if (!m_isX11) {
- if (m_xdgSurface && m_xdgSurface->m_toplevel)
- return m_xdgSurface->m_toplevel->m_state.title;
- } else {
- if (m_xwaylandSurface)
- return m_xwaylandSurface->m_state.title;
- }
-
- return "";
-}
-
-std::string CWindow::fetchClass() {
- if (!m_isX11) {
- if (m_xdgSurface && m_xdgSurface->m_toplevel)
- return m_xdgSurface->m_toplevel->m_state.appid;
- } else {
- if (m_xwaylandSurface)
- return m_xwaylandSurface->m_state.appid;
- }
-
- return "";
-}
-
-void CWindow::onAck(uint32_t serial) {
- const auto SERIAL = std::ranges::find_if(m_pendingSizeAcks | std::views::reverse, [serial](const auto& e) { return e.first <= serial; });
-
- if (SERIAL == m_pendingSizeAcks.rend())
- return;
-
- m_pendingSizeAck = *SERIAL;
- std::erase_if(m_pendingSizeAcks, [&](const auto& el) { return el.first <= SERIAL->first; });
-
- if (m_isX11)
- return;
-
- m_wlSurface->resource()->m_pending.ackedSize = m_pendingSizeAck->second; // apply pending size. We pinged, the window ponged.
- m_wlSurface->resource()->m_pending.updated.bits.acked = true;
- m_pendingSizeAck.reset();
-}
-
-void CWindow::onResourceChangeX11() {
- if (m_xwaylandSurface->m_surface && !m_wlSurface->resource())
- m_wlSurface->assign(m_xwaylandSurface->m_surface.lock(), m_self.lock());
- else if (!m_xwaylandSurface->m_surface && m_wlSurface->resource())
- m_wlSurface->unassign();
-
- // update metadata as well,
- // could be first assoc and we need to catch the class
- onUpdateMeta();
-
- Debug::log(LOG, "xwayland window {:x} -> association to {:x}", rc<uintptr_t>(m_xwaylandSurface.get()), rc<uintptr_t>(m_wlSurface->resource().get()));
-}
-
-void CWindow::onX11ConfigureRequest(CBox box) {
-
- if (!m_xwaylandSurface->m_surface || !m_xwaylandSurface->m_mapped || !m_isMapped) {
- m_xwaylandSurface->configure(box);
- m_pendingReportedSize = box.size();
- m_reportedSize = box.size();
- m_reportedPosition = box.pos();
- updateX11SurfaceScale();
- return;
- }
-
- g_pHyprRenderer->damageWindow(m_self.lock());
-
- if (!m_isFloating || isFullscreen() || g_pInputManager->m_currentlyDraggedWindow == m_self) {
- sendWindowSize(true);
- g_pInputManager->refocus();
- g_pHyprRenderer->damageWindow(m_self.lock());
- return;
- }
-
- if (box.size() > Vector2D{1, 1})
- setHidden(false);
- else
- setHidden(true);
-
- m_realPosition->setValueAndWarp(xwaylandPositionToReal(box.pos()));
- m_realSize->setValueAndWarp(xwaylandSizeToReal(box.size()));
-
- m_position = m_realPosition->goal();
- m_size = m_realSize->goal();
-
- if (m_pendingReportedSize != box.size() || m_reportedPosition != box.pos()) {
- m_xwaylandSurface->configure(box);
- m_reportedSize = box.size();
- m_pendingReportedSize = box.size();
- m_reportedPosition = box.pos();
- }
-
- updateX11SurfaceScale();
- updateWindowDecos();
-
- if (!m_workspace || !m_workspace->isVisible())
- return; // further things are only for visible windows
-
- m_workspace = g_pCompositor->getMonitorFromVector(m_realPosition->goal() + m_realSize->goal() / 2.f)->m_activeWorkspace;
-
- g_pCompositor->changeWindowZOrder(m_self.lock(), true);
-
- m_createdOverFullscreen = true;
-
- g_pHyprRenderer->damageWindow(m_self.lock());
-}
-
-void CWindow::warpCursor(bool force) {
- static auto PERSISTENTWARPS = CConfigValue<Hyprlang::INT>("cursor:persistent_warps");
- const auto coords = m_relativeCursorCoordsOnLastWarp;
- m_relativeCursorCoordsOnLastWarp.x = -1; // reset m_vRelativeCursorCoordsOnLastWarp
-
- if (*PERSISTENTWARPS && coords.x > 0 && coords.y > 0 && coords < m_size) // don't warp cursor outside the window
- g_pCompositor->warpCursorTo(m_position + coords, force);
- else
- g_pCompositor->warpCursorTo(middle(), force);
-}
-
-PHLWINDOW CWindow::getSwallower() {
- static auto PSWALLOWREGEX = CConfigValue<std::string>("misc:swallow_regex");
- static auto PSWALLOWEXREGEX = CConfigValue<std::string>("misc:swallow_exception_regex");
- static auto PSWALLOW = CConfigValue<Hyprlang::INT>("misc:enable_swallow");
-
- if (!*PSWALLOW || std::string{*PSWALLOWREGEX} == STRVAL_EMPTY || (*PSWALLOWREGEX).empty())
- return nullptr;
-
- // check parent
- std::vector<PHLWINDOW> candidates;
- pid_t currentPid = getPID();
- // walk up the tree until we find someone, 25 iterations max.
- for (size_t i = 0; i < 25; ++i) {
- currentPid = getPPIDof(currentPid);
-
- if (!currentPid)
- break;
-
- for (auto const& w : g_pCompositor->m_windows) {
- if (!w->m_isMapped || w->isHidden())
- continue;
-
- if (w->getPID() == currentPid)
- candidates.push_back(w);
- }
- }
-
- if (!(*PSWALLOWREGEX).empty())
- std::erase_if(candidates, [&](const auto& other) { return !RE2::FullMatch(other->m_class, *PSWALLOWREGEX); });
-
- if (candidates.empty())
- return nullptr;
-
- if (!(*PSWALLOWEXREGEX).empty())
- std::erase_if(candidates, [&](const auto& other) { return RE2::FullMatch(other->m_title, *PSWALLOWEXREGEX); });
-
- if (candidates.empty())
- return nullptr;
-
- if (candidates.size() == 1)
- return candidates[0];
-
- // walk up the focus history and find the last focused
- for (auto const& w : Desktop::focusState()->windowHistory()) {
- if (!w)
- continue;
-
- if (std::ranges::find(candidates.begin(), candidates.end(), w.lock()) != candidates.end())
- return w.lock();
- }
-
- // if none are found (??) then just return the first one
- return candidates[0];
-}
-
-bool CWindow::isX11OverrideRedirect() {
- return m_xwaylandSurface && m_xwaylandSurface->m_overrideRedirect;
-}
-
-bool CWindow::isModal() {
- return (m_xwaylandSurface && m_xwaylandSurface->m_modal);
-}
-
-Vector2D CWindow::requestedMinSize() {
- bool hasSizeHints = m_xwaylandSurface ? m_xwaylandSurface->m_sizeHints : false;
- bool hasTopLevel = m_xdgSurface ? m_xdgSurface->m_toplevel : false;
- if ((m_isX11 && !hasSizeHints) || (!m_isX11 && !hasTopLevel))
- return Vector2D(1, 1);
-
- Vector2D minSize = m_isX11 ? Vector2D(m_xwaylandSurface->m_sizeHints->min_width, m_xwaylandSurface->m_sizeHints->min_height) : m_xdgSurface->m_toplevel->layoutMinSize();
-
- minSize = minSize.clamp({1, 1});
-
- return minSize;
-}
-
-Vector2D CWindow::requestedMaxSize() {
- constexpr int NO_MAX_SIZE_LIMIT = 99999;
- if (((m_isX11 && !m_xwaylandSurface->m_sizeHints) || (!m_isX11 && (!m_xdgSurface || !m_xdgSurface->m_toplevel)) || m_ruleApplicator->noMaxSize().valueOrDefault()))
- return Vector2D(NO_MAX_SIZE_LIMIT, NO_MAX_SIZE_LIMIT);
-
- Vector2D maxSize = m_isX11 ? Vector2D(m_xwaylandSurface->m_sizeHints->max_width, m_xwaylandSurface->m_sizeHints->max_height) : m_xdgSurface->m_toplevel->layoutMaxSize();
-
- if (maxSize.x < 5)
- maxSize.x = NO_MAX_SIZE_LIMIT;
- if (maxSize.y < 5)
- maxSize.y = NO_MAX_SIZE_LIMIT;
-
- return maxSize;
-}
-
-Vector2D CWindow::realToReportSize() {
- if (!m_isX11)
- return m_realSize->goal().clamp(Vector2D{0, 0}, Vector2D{std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity()});
-
- static auto PXWLFORCESCALEZERO = CConfigValue<Hyprlang::INT>("xwayland:force_zero_scaling");
-
- const auto REPORTSIZE = m_realSize->goal().clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity()});
- const auto PMONITOR = m_monitor.lock();
-
- if (*PXWLFORCESCALEZERO && PMONITOR)
- return REPORTSIZE * PMONITOR->m_scale;
-
- return REPORTSIZE;
-}
-
-Vector2D CWindow::realToReportPosition() {
- if (!m_isX11)
- return m_realPosition->goal();
-
- return g_pXWaylandManager->waylandToXWaylandCoords(m_realPosition->goal());
-}
-
-Vector2D CWindow::xwaylandSizeToReal(Vector2D size) {
- static auto PXWLFORCESCALEZERO = CConfigValue<Hyprlang::INT>("xwayland:force_zero_scaling");
-
- const auto PMONITOR = m_monitor.lock();
- const auto SIZE = size.clamp(Vector2D{1, 1}, Vector2D{std::numeric_limits<double>::infinity(), std::numeric_limits<double>::infinity()});
- const auto SCALE = *PXWLFORCESCALEZERO ? PMONITOR->m_scale : 1.0f;
-
- return SIZE / SCALE;
-}
-
-Vector2D CWindow::xwaylandPositionToReal(Vector2D pos) {
- return g_pXWaylandManager->xwaylandToWaylandCoords(pos);
-}
-
-void CWindow::updateX11SurfaceScale() {
- static auto PXWLFORCESCALEZERO = CConfigValue<Hyprlang::INT>("xwayland:force_zero_scaling");
-
- m_X11SurfaceScaledBy = 1.0f;
- if (m_isX11 && *PXWLFORCESCALEZERO) {
- if (const auto PMONITOR = m_monitor.lock(); PMONITOR)
- m_X11SurfaceScaledBy = PMONITOR->m_scale;
- }
-}
-
-void CWindow::sendWindowSize(bool force) {
- const auto PMONITOR = m_monitor.lock();
-
- Debug::log(TRACE, "sendWindowSize: window:{:x},title:{} with real pos {}, real size {} (force: {})", rc<uintptr_t>(this), this->m_title, m_realPosition->goal(),
- m_realSize->goal(), force);
-
- // TODO: this should be decoupled from setWindowSize IMO
- const auto REPORTPOS = realToReportPosition();
-
- const auto REPORTSIZE = realToReportSize();
-
- if (!force && m_pendingReportedSize == REPORTSIZE && (m_reportedPosition == REPORTPOS || !m_isX11))
- return;
-
- m_reportedPosition = REPORTPOS;
- m_pendingReportedSize = REPORTSIZE;
- updateX11SurfaceScale();
-
- if (m_isX11 && m_xwaylandSurface)
- m_xwaylandSurface->configure({REPORTPOS, REPORTSIZE});
- else if (m_xdgSurface && m_xdgSurface->m_toplevel)
- m_pendingSizeAcks.emplace_back(m_xdgSurface->m_toplevel->setSize(REPORTSIZE), REPORTSIZE.floor());
-}
-
-NContentType::eContentType CWindow::getContentType() {
- if (!m_wlSurface || !m_wlSurface->resource() || !m_wlSurface->resource()->m_contentType.valid())
- return CONTENT_TYPE_NONE;
-
- return m_wlSurface->resource()->m_contentType->m_value;
-}
-
-void CWindow::setContentType(NContentType::eContentType contentType) {
- if (!m_wlSurface->resource()->m_contentType.valid())
- m_wlSurface->resource()->m_contentType = PROTO::contentType->getContentType(m_wlSurface->resource());
- // else disallow content type change if proto is used?
-
- Debug::log(INFO, "ContentType for window {}", sc<int>(contentType));
- m_wlSurface->resource()->m_contentType->m_value = contentType;
-}
-
-void CWindow::deactivateGroupMembers() {
- auto curr = getGroupHead();
- while (curr) {
- if (curr != m_self.lock()) {
- // we don't want to deactivate unfocused xwayland windows
- // because X is weird, keep the behavior for wayland windows
- // also its not really needed for xwayland windows
- // ref: #9760 #9294
- if (!curr->m_isX11 && curr->m_xdgSurface && curr->m_xdgSurface->m_toplevel)
- curr->m_xdgSurface->m_toplevel->setActive(false);
- }
-
- curr = curr->m_groupData.pNextWindow.lock();
- if (curr == getGroupHead())
- break;
- }
-}
-
-bool CWindow::isNotResponding() {
- return g_pANRManager->isNotResponding(m_self.lock());
-}
-
-std::optional<std::string> CWindow::xdgTag() {
- if (!m_xdgSurface || !m_xdgSurface->m_toplevel)
- return std::nullopt;
-
- return m_xdgSurface->m_toplevel->m_toplevelTag;
-}
-
-std::optional<std::string> CWindow::xdgDescription() {
- if (!m_xdgSurface || !m_xdgSurface->m_toplevel)
- return std::nullopt;
-
- return m_xdgSurface->m_toplevel->m_toplevelDescription;
-}
-
-PHLWINDOW CWindow::parent() {
- if (m_isX11) {
- auto t = x11TransientFor();
-
- // don't return a parent that's not mapped
- if (!validMapped(t))
- return nullptr;
-
- return t;
- }
-
- if (!m_xdgSurface || !m_xdgSurface->m_toplevel || !m_xdgSurface->m_toplevel->m_parent)
- return nullptr;
-
- // don't return a parent that's not mapped
- if (!m_xdgSurface->m_toplevel->m_parent->m_window || !validMapped(m_xdgSurface->m_toplevel->m_parent->m_window))
- return nullptr;
-
- return m_xdgSurface->m_toplevel->m_parent->m_window.lock();
-}
-
-bool CWindow::priorityFocus() {
- return !m_isX11 && CAsyncDialogBox::isPriorityDialogBox(getPID());
-}
-
-SP<CWLSurfaceResource> CWindow::getSolitaryResource() {
- if (!m_wlSurface || !m_wlSurface->resource())
- return nullptr;
-
- auto res = m_wlSurface->resource();
- if (m_isX11)
- return res;
-
- if (popupsCount())
- return nullptr;
-
- if (res->m_subsurfaces.size() == 0)
- return res;
-
- if (res->m_subsurfaces.size() >= 1) {
- if (!res->hasVisibleSubsurface())
- return res;
-
- if (res->m_subsurfaces.size() == 1) {
- if (res->m_subsurfaces[0].expired() || res->m_subsurfaces[0]->m_surface.expired())
- return nullptr;
- auto surf = res->m_subsurfaces[0]->m_surface.lock();
- if (!surf || surf->m_subsurfaces.size() != 0 || surf->extends() != res->extends() || !surf->m_current.texture || !surf->m_current.texture->m_opaque)
- return nullptr;
- return surf;
- }
- }
-
- return nullptr;
-}
-
-Vector2D CWindow::getReportedSize() {
- if (m_isX11)
- return m_reportedSize;
- if (m_wlSurface && m_wlSurface->resource())
- return m_wlSurface->resource()->m_current.ackedSize;
- return m_reportedSize;
-}
-
-void CWindow::updateDecorationValues() {
- static auto PACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.active_border");
- static auto PINACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.inactive_border");
- static auto PNOGROUPACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.nogroup_border_active");
- static auto PNOGROUPINACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("general:col.nogroup_border");
- static auto PGROUPACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_active");
- static auto PGROUPINACTIVECOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_inactive");
- static auto PGROUPACTIVELOCKEDCOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_locked_active");
- static auto PGROUPINACTIVELOCKEDCOL = CConfigValue<Hyprlang::CUSTOMTYPE>("group:col.border_locked_inactive");
- static auto PINACTIVEALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:inactive_opacity");
- static auto PACTIVEALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:active_opacity");
- static auto PFULLSCREENALPHA = CConfigValue<Hyprlang::FLOAT>("decoration:fullscreen_opacity");
- static auto PSHADOWCOL = CConfigValue<Hyprlang::INT>("decoration:shadow:color");
- static auto PSHADOWCOLINACTIVE = CConfigValue<Hyprlang::INT>("decoration:shadow:color_inactive");
- static auto PDIMSTRENGTH = CConfigValue<Hyprlang::FLOAT>("decoration:dim_strength");
- static auto PDIMENABLED = CConfigValue<Hyprlang::INT>("decoration:dim_inactive");
- static auto PDIMMODAL = CConfigValue<Hyprlang::INT>("decoration:dim_modal");
-
- auto* const ACTIVECOL = sc<CGradientValueData*>((PACTIVECOL.ptr())->getData());
- auto* const INACTIVECOL = sc<CGradientValueData*>((PINACTIVECOL.ptr())->getData());
- auto* const NOGROUPACTIVECOL = sc<CGradientValueData*>((PNOGROUPACTIVECOL.ptr())->getData());
- auto* const NOGROUPINACTIVECOL = sc<CGradientValueData*>((PNOGROUPINACTIVECOL.ptr())->getData());
- auto* const GROUPACTIVECOL = sc<CGradientValueData*>((PGROUPACTIVECOL.ptr())->getData());
- auto* const GROUPINACTIVECOL = sc<CGradientValueData*>((PGROUPINACTIVECOL.ptr())->getData());
- auto* const GROUPACTIVELOCKEDCOL = sc<CGradientValueData*>((PGROUPACTIVELOCKEDCOL.ptr())->getData());
- auto* const GROUPINACTIVELOCKEDCOL = sc<CGradientValueData*>((PGROUPINACTIVELOCKEDCOL.ptr())->getData());
-
- auto setBorderColor = [&](CGradientValueData grad) -> void {
- if (grad == m_realBorderColor)
- return;
-
- m_realBorderColorPrevious = m_realBorderColor;
- m_realBorderColor = grad;
- m_borderFadeAnimationProgress->setValueAndWarp(0.f);
- *m_borderFadeAnimationProgress = 1.f;
- };
-
- const bool IS_SHADOWED_BY_MODAL = m_xdgSurface && m_xdgSurface->m_toplevel && m_xdgSurface->m_toplevel->anyChildModal();
-
- // border
- const auto RENDERDATA = g_pLayoutManager->getCurrentLayout()->requestRenderHints(m_self.lock());
- if (RENDERDATA.isBorderGradient)
- setBorderColor(*RENDERDATA.borderGradient);
- else {
- const bool GROUPLOCKED = m_groupData.pNextWindow.lock() ? getGroupHead()->m_groupData.locked : false;
- if (m_self == Desktop::focusState()->window()) {
- const auto* const ACTIVECOLOR =
- !m_groupData.pNextWindow.lock() ? (!m_groupData.deny ? ACTIVECOL : NOGROUPACTIVECOL) : (GROUPLOCKED ? GROUPACTIVELOCKEDCOL : GROUPACTIVECOL);
- setBorderColor(m_ruleApplicator->activeBorderColor().valueOr(*ACTIVECOLOR));
- } else {
- const auto* const INACTIVECOLOR =
- !m_groupData.pNextWindow.lock() ? (!m_groupData.deny ? INACTIVECOL : NOGROUPINACTIVECOL) : (GROUPLOCKED ? GROUPINACTIVELOCKEDCOL : GROUPINACTIVECOL);
- setBorderColor(m_ruleApplicator->inactiveBorderColor().valueOr(*INACTIVECOLOR));
- }
- }
-
- // opacity
- const auto PWORKSPACE = m_workspace;
- if (isEffectiveInternalFSMode(FSMODE_FULLSCREEN)) {
- *m_activeInactiveAlpha = m_ruleApplicator->alphaFullscreen().valueOrDefault().applyAlpha(*PFULLSCREENALPHA);
- } else {
- if (m_self == Desktop::focusState()->window())
- *m_activeInactiveAlpha = m_ruleApplicator->alpha().valueOrDefault().applyAlpha(*PACTIVEALPHA);
- else
- *m_activeInactiveAlpha = m_ruleApplicator->alphaInactive().valueOrDefault().applyAlpha(*PINACTIVEALPHA);
- }
-
- // dim
- float goalDim = 1.F;
- if (m_self == Desktop::focusState()->window() || m_ruleApplicator->noDim().valueOrDefault() || !*PDIMENABLED)
- goalDim = 0;
- else
- goalDim = *PDIMSTRENGTH;
-
- if (IS_SHADOWED_BY_MODAL && *PDIMMODAL)
- goalDim += (1.F - goalDim) / 2.F;
-
- *m_dimPercent = goalDim;
-
- // shadow
- if (!isX11OverrideRedirect() && !m_X11DoesntWantBorders) {
- if (m_self == Desktop::focusState()->window())
- *m_realShadowColor = CHyprColor(*PSHADOWCOL);
- else
- *m_realShadowColor = CHyprColor(*PSHADOWCOLINACTIVE != -1 ? *PSHADOWCOLINACTIVE : *PSHADOWCOL);
- } else
- m_realShadowColor->setValueAndWarp(CHyprColor(0, 0, 0, 0)); // no shadow
-
- updateWindowDecos();
-}
-
-std::optional<double> CWindow::calculateSingleExpr(const std::string& s) {
- const auto PMONITOR = m_monitor ? m_monitor : Desktop::focusState()->monitor();
- const auto CURSOR_LOCAL = g_pInputManager->getMouseCoordsInternal() - (PMONITOR ? PMONITOR->m_position : Vector2D{});
-
- Math::CExpression expr;
- expr.addVariable("window_w", m_realSize->goal().x);
- expr.addVariable("window_h", m_realSize->goal().y);
- expr.addVariable("window_x", m_realPosition->goal().x - (PMONITOR ? PMONITOR->m_position.x : 0));
- expr.addVariable("window_y", m_realPosition->goal().y - (PMONITOR ? PMONITOR->m_position.y : 0));
-
- expr.addVariable("monitor_w", PMONITOR ? PMONITOR->m_size.x : 1920);
- expr.addVariable("monitor_h", PMONITOR ? PMONITOR->m_size.y : 1080);
-
- expr.addVariable("cursor_x", CURSOR_LOCAL.x);
- expr.addVariable("cursor_y", CURSOR_LOCAL.y);
-
- return expr.compute(s);
-}
-
-std::optional<Vector2D> CWindow::calculateExpression(const std::string& s) {
- auto spacePos = s.find(' ');
- if (spacePos == std::string::npos)
- return std::nullopt;
-
- const auto LHS = calculateSingleExpr(s.substr(0, spacePos));
- const auto RHS = calculateSingleExpr(s.substr(spacePos + 1));
-
- if (!LHS || !RHS)
- return std::nullopt;
-
- return Vector2D{*LHS, *RHS};
-}