From b39dcfa497f84486569bf862092dfcfadbfd8747 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 29 Feb 2024 13:03:38 +0000 Subject: refactor: move a few things to desktop/ --- src/Compositor.hpp | 2 +- src/Window.hpp | 4 +- src/desktop/Subsurface.cpp | 238 +++++++++++++++++++++++++++++++++++++++++++++ src/desktop/Subsurface.hpp | 53 ++++++++++ src/desktop/WLSurface.cpp | 110 +++++++++++++++++++++ src/desktop/WLSurface.hpp | 72 ++++++++++++++ src/desktop/Workspace.cpp | 180 ++++++++++++++++++++++++++++++++++ src/desktop/Workspace.hpp | 67 +++++++++++++ src/helpers/Subsurface.cpp | 238 --------------------------------------------- src/helpers/Subsurface.hpp | 51 ---------- src/helpers/WLClasses.hpp | 4 +- src/helpers/WLSurface.cpp | 110 --------------------- src/helpers/WLSurface.hpp | 72 -------------- src/helpers/Workspace.cpp | 180 ---------------------------------- src/helpers/Workspace.hpp | 67 ------------- src/render/Renderer.hpp | 2 +- 16 files changed, 726 insertions(+), 724 deletions(-) create mode 100644 src/desktop/Subsurface.cpp create mode 100644 src/desktop/Subsurface.hpp create mode 100644 src/desktop/WLSurface.cpp create mode 100644 src/desktop/WLSurface.hpp create mode 100644 src/desktop/Workspace.cpp create mode 100644 src/desktop/Workspace.hpp delete mode 100644 src/helpers/Subsurface.cpp delete mode 100644 src/helpers/Subsurface.hpp delete mode 100644 src/helpers/WLSurface.cpp delete mode 100644 src/helpers/WLSurface.hpp delete mode 100644 src/helpers/Workspace.cpp delete mode 100644 src/helpers/Workspace.hpp (limited to 'src') diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 491aee71..92573669 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -21,7 +21,7 @@ #include "debug/HyprDebugOverlay.hpp" #include "debug/HyprNotificationOverlay.hpp" #include "helpers/Monitor.hpp" -#include "helpers/Workspace.hpp" +#include "desktop/Workspace.hpp" #include "Window.hpp" #include "render/Renderer.hpp" #include "render/OpenGL.hpp" diff --git a/src/Window.hpp b/src/Window.hpp index 2d7bc986..476cb1c5 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -1,13 +1,13 @@ #pragma once #include "defines.hpp" -#include "helpers/Subsurface.hpp" +#include "desktop/Subsurface.hpp" #include "helpers/AnimatedVariable.hpp" #include "render/decorations/IHyprWindowDecoration.hpp" #include #include "config/ConfigDataValues.hpp" #include "helpers/Vector2D.hpp" -#include "helpers/WLSurface.hpp" +#include "desktop/WLSurface.hpp" #include "macros.hpp" #include "managers/XWaylandManager.hpp" diff --git a/src/desktop/Subsurface.cpp b/src/desktop/Subsurface.cpp new file mode 100644 index 00000000..0923e9cc --- /dev/null +++ b/src/desktop/Subsurface.cpp @@ -0,0 +1,238 @@ +#include "Subsurface.hpp" +#include "../events/Events.hpp" +#include "../Compositor.hpp" + +static void onNewSubsurface(void* owner, void* data); + +CSubsurface::CSubsurface(CWindow* pOwner) : m_pWindowParent(pOwner) { + initSignals(); + + wlr_subsurface* wlrSubsurface; + wl_list_for_each(wlrSubsurface, &pOwner->m_pWLSurface.wlr()->current.subsurfaces_below, current.link) { + ::onNewSubsurface(this, wlrSubsurface); + } + wl_list_for_each(wlrSubsurface, &pOwner->m_pWLSurface.wlr()->current.subsurfaces_above, current.link) { + ::onNewSubsurface(this, wlrSubsurface); + } +} + +CSubsurface::CSubsurface(wlr_subsurface* pSubsurface, CWindow* pOwner) : m_pSubsurface(pSubsurface), m_pWindowParent(pOwner) { + m_sWLSurface.assign(pSubsurface->surface); + initSignals(); + initExistingSubsurfaces(); +} + +CSubsurface::~CSubsurface() { + hyprListener_newSubsurface.removeCallback(); + + if (!m_pSubsurface) + return; + + hyprListener_commitSubsurface.removeCallback(); + hyprListener_destroySubsurface.removeCallback(); + + const auto COORDS = coordsGlobal(); + + CBox box = {COORDS, m_vLastSize}; + g_pHyprRenderer->damageBox(&box); +} + +static void onNewSubsurface(void* owner, void* data) { + const auto PSUBSURFACE = (CSubsurface*)owner; + PSUBSURFACE->onNewSubsurface((wlr_subsurface*)data); +} + +static void onDestroySubsurface(void* owner, void* data) { + const auto PSUBSURFACE = (CSubsurface*)owner; + PSUBSURFACE->onDestroy(); +} + +static void onCommitSubsurface(void* owner, void* data) { + const auto PSUBSURFACE = (CSubsurface*)owner; + PSUBSURFACE->onCommit(); +} + +static void onMapSubsurface(void* owner, void* data) { + const auto PSUBSURFACE = (CSubsurface*)owner; + PSUBSURFACE->onMap(); +} + +static void onUnmapSubsurface(void* owner, void* data) { + const auto PSUBSURFACE = (CSubsurface*)owner; + PSUBSURFACE->onUnmap(); +} + +void CSubsurface::initSignals() { + if (m_pSubsurface) { + hyprListener_commitSubsurface.initCallback(&m_pSubsurface->surface->events.commit, &onCommitSubsurface, this, "CSubsurface"); + hyprListener_destroySubsurface.initCallback(&m_pSubsurface->events.destroy, &onDestroySubsurface, this, "CSubsurface"); + hyprListener_newSubsurface.initCallback(&m_pSubsurface->surface->events.new_subsurface, &::onNewSubsurface, this, "CSubsurface"); + hyprListener_mapSubsurface.initCallback(&m_pSubsurface->surface->events.map, &onMapSubsurface, this, "CSubsurface"); + hyprListener_newSubsurface.initCallback(&m_pSubsurface->surface->events.unmap, &onUnmapSubsurface, this, "CSubsurface"); + } else { + if (m_pWindowParent) + hyprListener_newSubsurface.initCallback(&m_pWindowParent->m_pWLSurface.wlr()->events.new_subsurface, &::onNewSubsurface, this, "CSubsurface"); + else + RASSERT(false, "CSubsurface::initSignals empty subsurface"); + } +} + +void CSubsurface::checkSiblingDamage() { + if (!m_pParent) + return; // ?????????? + + const double SCALE = m_pWindowParent && m_pWindowParent->m_bIsX11 ? 1.0 / m_pWindowParent->m_fX11SurfaceScaledBy : 1.0; + + for (auto& n : m_pParent->m_vChildren) { + if (n.get() == this) + continue; + + const auto COORDS = n->coordsGlobal(); + g_pHyprRenderer->damageSurface(n->m_sWLSurface.wlr(), COORDS.x, COORDS.y, SCALE); + } +} + +void CSubsurface::recheckDamageForSubsurfaces() { + const double SCALE = m_pWindowParent && m_pWindowParent->m_bIsX11 ? 1.0 / m_pWindowParent->m_fX11SurfaceScaledBy : 1.0; + + for (auto& n : m_vChildren) { + const auto COORDS = n->coordsGlobal(); + g_pHyprRenderer->damageSurface(n->m_sWLSurface.wlr(), COORDS.x, COORDS.y, SCALE); + } +} + +void CSubsurface::onCommit() { + // no damaging if it's not visible + if (!g_pHyprRenderer->shouldRenderWindow(m_pWindowParent)) { + m_vLastSize = Vector2D{m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}; + + static auto* const PLOGDAMAGE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:log_damage"); + if (**PLOGDAMAGE) + Debug::log(LOG, "Refusing to commit damage from a subsurface of {} because it's invisible.", m_pWindowParent); + return; + } + + const auto COORDS = coordsGlobal(); + + const double SCALE = m_pWindowParent && m_pWindowParent->m_bIsX11 ? 1.0 / m_pWindowParent->m_fX11SurfaceScaledBy : 1.0; + + g_pHyprRenderer->damageSurface(m_sWLSurface.wlr(), COORDS.x, COORDS.y, SCALE); + + // I do not think this is correct, but it solves a lot of issues with some apps (e.g. firefox) + checkSiblingDamage(); + + if (m_vLastSize != Vector2D{m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}) { + CBox box{COORDS, m_vLastSize}; + g_pHyprRenderer->damageBox(&box); + m_vLastSize = Vector2D{m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}; + box = {COORDS, m_vLastSize}; + g_pHyprRenderer->damageBox(&box); + } + + if (m_pWindowParent) { + if (m_pWindowParent->m_bIsX11) + m_pWindowParent->m_vReportedSize = m_pWindowParent->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged. + + // tearing: if solitary, redraw it. This still might be a single surface window + const auto PMONITOR = g_pCompositor->getMonitorFromID(m_pWindowParent->m_iMonitorID); + if (PMONITOR && PMONITOR->solitaryClient == m_pWindowParent && m_pWindowParent->canBeTorn() && PMONITOR->tearingState.canTear && + m_sWLSurface.wlr()->current.committed & WLR_SURFACE_STATE_BUFFER) { + CRegion damageBox{&m_sWLSurface.wlr()->buffer_damage}; + + if (!damageBox.empty()) { + if (PMONITOR->tearingState.busy) { + PMONITOR->tearingState.frameScheduledWhileBusy = true; + } else { + PMONITOR->tearingState.nextRenderTorn = true; + g_pHyprRenderer->renderMonitor(PMONITOR); + } + } + } + } +} + +void CSubsurface::onDestroy() { + // destroy children + m_vChildren.clear(); + + if (!m_pSubsurface) + return; // dummy node, nothing to do, it's the parent dying + + // kill ourselves + std::erase_if(m_pParent->m_vChildren, [this](const auto& other) { return other.get() == this; }); +} + +void CSubsurface::onNewSubsurface(wlr_subsurface* pSubsurface) { + CSubsurface* PSUBSURFACE = nullptr; + + if (m_pWindowParent) + PSUBSURFACE = m_vChildren.emplace_back(std::make_unique(pSubsurface, m_pWindowParent)).get(); + PSUBSURFACE->m_pParent = this; + + ASSERT(PSUBSURFACE); +} + +void CSubsurface::onMap() { + m_vLastSize = {m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}; + + const auto COORDS = coordsGlobal(); + CBox box{COORDS, m_vLastSize}; + g_pHyprRenderer->damageBox(&box); + + if (m_pWindowParent) + m_pWindowParent->updateSurfaceScaleTransformDetails(); +} + +void CSubsurface::onUnmap() { + const auto COORDS = coordsGlobal(); + CBox box{COORDS, m_vLastSize}; + g_pHyprRenderer->damageBox(&box); + + if (m_sWLSurface.wlr() == g_pCompositor->m_pLastFocus) + g_pInputManager->releaseAllMouseButtons(); + + if (m_pWindowParent) + m_pWindowParent->updateSurfaceScaleTransformDetails(); + + g_pInputManager->simulateMouseMovement(); + + // TODO: should this remove children? Currently it won't, only on .destroy +} + +Vector2D CSubsurface::coordsRelativeToParent() { + Vector2D offset; + + CSubsurface* current = this; + + while (current->m_pParent) { + + offset += {current->m_sWLSurface.wlr()->current.dx, current->m_sWLSurface.wlr()->current.dy}; + offset += {current->m_pSubsurface->current.x, current->m_pSubsurface->current.y}; + + current = current->m_pParent; + } + + return offset; +} + +Vector2D CSubsurface::coordsGlobal() { + Vector2D coords = coordsRelativeToParent(); + + if (m_pWindowParent) + coords += m_pWindowParent->m_vRealPosition.vec(); + + return coords; +} + +void CSubsurface::initExistingSubsurfaces() { + if (m_pWindowParent) + return; + + wlr_subsurface* wlrSubsurface; + wl_list_for_each(wlrSubsurface, &m_sWLSurface.wlr()->current.subsurfaces_below, current.link) { + ::onNewSubsurface(this, wlrSubsurface); + } + wl_list_for_each(wlrSubsurface, &m_sWLSurface.wlr()->current.subsurfaces_above, current.link) { + ::onNewSubsurface(this, wlrSubsurface); + } +} \ No newline at end of file diff --git a/src/desktop/Subsurface.hpp b/src/desktop/Subsurface.hpp new file mode 100644 index 00000000..22692192 --- /dev/null +++ b/src/desktop/Subsurface.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include "../defines.hpp" +#include +#include "WLSurface.hpp" + +class CWindow; +struct SXDGPopup; + +class CSubsurface { + public: + // root dummy nodes + CSubsurface(CWindow* pOwner); + + // real nodes + CSubsurface(wlr_subsurface* pSubsurface, CWindow* pOwner); + + ~CSubsurface(); + + Vector2D coordsRelativeToParent(); + Vector2D coordsGlobal(); + + void onCommit(); + void onDestroy(); + void onNewSubsurface(wlr_subsurface* pSubsurface); + void onMap(); + void onUnmap(); + + void recheckDamageForSubsurfaces(); + + private: + + DYNLISTENER(destroySubsurface); + DYNLISTENER(commitSubsurface); + DYNLISTENER(newSubsurface); + DYNLISTENER(mapSubsurface); + DYNLISTENER(unmapSubsurface); + + wlr_subsurface* m_pSubsurface = nullptr; + CWLSurface m_sWLSurface; + Vector2D m_vLastSize = {}; + + // if nullptr, means it's a dummy node + CSubsurface* m_pParent = nullptr; + + CWindow* m_pWindowParent = nullptr; + + std::vector> m_vChildren; + + void initSignals(); + void initExistingSubsurfaces(); + void checkSiblingDamage(); +}; \ No newline at end of file diff --git a/src/desktop/WLSurface.cpp b/src/desktop/WLSurface.cpp new file mode 100644 index 00000000..25f11feb --- /dev/null +++ b/src/desktop/WLSurface.cpp @@ -0,0 +1,110 @@ +#include "WLSurface.hpp" +#include "../Compositor.hpp" + +CWLSurface::CWLSurface(wlr_surface* pSurface) { + m_pWLRSurface = pSurface; + init(); +} + +void CWLSurface::assign(wlr_surface* pSurface) { + m_pWLRSurface = pSurface; + init(); +} + +void CWLSurface::unassign() { + destroy(); +} + +CWLSurface::~CWLSurface() { + destroy(); +} + +bool CWLSurface::exists() const { + return m_pWLRSurface; +} + +wlr_surface* CWLSurface::wlr() const { + return m_pWLRSurface; +} + +bool CWLSurface::small() const { + if (!m_pOwner || !exists()) + return false; + + return m_pOwner->m_vReportedSize.x > m_pWLRSurface->current.buffer_width + 1 || m_pOwner->m_vReportedSize.y > m_pWLRSurface->current.buffer_height + 1; +} + +Vector2D CWLSurface::correctSmallVec() const { + if (!m_pOwner || !exists() || !small() || m_bFillIgnoreSmall) + return {}; + + const auto SIZE = getViewporterCorrectedSize(); + + return Vector2D{(m_pOwner->m_vReportedSize.x - SIZE.x) / 2, (m_pOwner->m_vReportedSize.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}) * + (m_pOwner->m_vRealSize.vec() / m_pOwner->m_vReportedSize); +} + +Vector2D CWLSurface::getViewporterCorrectedSize() const { + if (!exists()) + return {}; + + return m_pWLRSurface->current.viewport.has_dst ? Vector2D{m_pWLRSurface->current.viewport.dst_width, m_pWLRSurface->current.viewport.dst_height} : + Vector2D{m_pWLRSurface->current.buffer_width, m_pWLRSurface->current.buffer_height}; +} + +CRegion CWLSurface::logicalDamage() const { + CRegion damage{&m_pWLRSurface->buffer_damage}; + damage.transform(m_pWLRSurface->current.transform, m_pWLRSurface->current.buffer_width, m_pWLRSurface->current.buffer_height); + damage.scale(1.0 / m_pWLRSurface->current.scale); + + const auto VPSIZE = getViewporterCorrectedSize(); + const auto CORRECTVEC = correctSmallVec(); + + if (m_pWLRSurface->current.viewport.has_src) { + damage.intersect(CBox{std::floor(m_pWLRSurface->current.viewport.src.x), std::floor(m_pWLRSurface->current.viewport.src.y), + std::ceil(m_pWLRSurface->current.viewport.src.width), std::ceil(m_pWLRSurface->current.viewport.src.height)}); + } + + const auto SCALEDSRCSIZE = m_pWLRSurface->current.viewport.has_src ? + Vector2D{m_pWLRSurface->current.viewport.src.width, m_pWLRSurface->current.viewport.src.height} * m_pWLRSurface->current.scale : + Vector2D{m_pWLRSurface->current.buffer_width, m_pWLRSurface->current.buffer_height}; + + damage.scale({VPSIZE.x / SCALEDSRCSIZE.x, VPSIZE.y / SCALEDSRCSIZE.y}); + damage.translate(CORRECTVEC); + + return damage; +} + +void CWLSurface::destroy() { + if (!m_pWLRSurface) + return; + + hyprListener_destroy.removeCallback(); + m_pWLRSurface->data = nullptr; + m_pOwner = nullptr; + + if (g_pCompositor && g_pCompositor->m_pLastFocus == m_pWLRSurface) + g_pCompositor->m_pLastFocus = nullptr; + if (g_pInputManager && g_pInputManager->m_pLastMouseSurface == m_pWLRSurface) + g_pInputManager->m_pLastMouseSurface = nullptr; + if (g_pHyprRenderer && g_pHyprRenderer->m_sLastCursorData.surf == m_pWLRSurface) + g_pHyprRenderer->m_sLastCursorData.surf.reset(); + + m_pWLRSurface = nullptr; + + Debug::log(LOG, "CWLSurface {:x} called destroy()", (uintptr_t)this); +} + +void CWLSurface::init() { + if (!m_pWLRSurface) + return; + + RASSERT(!m_pWLRSurface->data, "Attempted to duplicate CWLSurface ownership!"); + + m_pWLRSurface->data = this; + + hyprListener_destroy.initCallback( + &m_pWLRSurface->events.destroy, [&](void* owner, void* data) { destroy(); }, this, "CWLSurface"); + + Debug::log(LOG, "CWLSurface {:x} called init()", (uintptr_t)this); +} \ No newline at end of file diff --git a/src/desktop/WLSurface.hpp b/src/desktop/WLSurface.hpp new file mode 100644 index 00000000..15debd56 --- /dev/null +++ b/src/desktop/WLSurface.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include "../defines.hpp" +#include "../helpers/Region.hpp" + +class CWindow; + +class CWLSurface { + public: + CWLSurface() = default; + CWLSurface(wlr_surface* pSurface); + ~CWLSurface(); + + void assign(wlr_surface* pSurface); + void unassign(); + + CWLSurface(const CWLSurface&) = delete; + CWLSurface(CWLSurface&&) = delete; + CWLSurface& operator=(const CWLSurface&) = delete; + CWLSurface& operator=(CWLSurface&&) = delete; + + wlr_surface* wlr() const; + bool exists() const; + bool small() const; // means surface is smaller than the requested size + Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces + Vector2D getViewporterCorrectedSize() const; + CRegion logicalDamage() const; + + // allow stretching. Useful for plugins. + bool m_bFillIgnoreSmall = false; + + // if present, means this is a base surface of a window. Cleaned on unassign() + CWindow* m_pOwner = nullptr; + + // track surface data and avoid dupes + float m_fLastScale = 0; + int m_iLastScale = 0; + wl_output_transform m_eLastTransform = (wl_output_transform)-1; + + // + CWLSurface& operator=(wlr_surface* pSurface) { + destroy(); + m_pWLRSurface = pSurface; + init(); + + return *this; + } + + bool operator==(const CWLSurface& other) const { + return other.wlr() == wlr(); + } + + bool operator==(const wlr_surface* other) const { + return other == wlr(); + } + + explicit operator bool() const { + return exists(); + } + + static CWLSurface* surfaceFromWlr(wlr_surface* pSurface) { + return (CWLSurface*)pSurface->data; + } + + private: + wlr_surface* m_pWLRSurface = nullptr; + + void destroy(); + void init(); + + DYNLISTENER(destroy); +}; \ No newline at end of file diff --git a/src/desktop/Workspace.cpp b/src/desktop/Workspace.cpp new file mode 100644 index 00000000..ad8ae4ad --- /dev/null +++ b/src/desktop/Workspace.cpp @@ -0,0 +1,180 @@ +#include "Workspace.hpp" +#include "../Compositor.hpp" + +CWorkspace::CWorkspace(int monitorID, std::string name, bool special) { + const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID); + + if (!PMONITOR) { + Debug::log(ERR, "Attempted a creation of CWorkspace with an invalid monitor?"); + return; + } + + m_iMonitorID = monitorID; + m_szName = name; + m_bIsSpecialWorkspace = special; + + m_vRenderOffset.m_pWorkspace = this; + m_vRenderOffset.create(AVARTYPE_VECTOR, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), + nullptr, AVARDAMAGE_ENTIRE); + m_fAlpha.m_pWorkspace = this; + m_fAlpha.create(AVARTYPE_FLOAT, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), + nullptr, AVARDAMAGE_ENTIRE); + m_fAlpha.setValueAndWarp(1.f); + + m_vRenderOffset.registerVar(); + m_fAlpha.registerVar(); + + const auto RULEFORTHIS = g_pConfigManager->getWorkspaceRuleFor(this); + if (RULEFORTHIS.defaultName.has_value()) + m_szName = RULEFORTHIS.defaultName.value(); + + g_pEventManager->postEvent({"createworkspace", m_szName}); + EMIT_HOOK_EVENT("createWorkspace", this); +} + +CWorkspace::~CWorkspace() { + m_vRenderOffset.unregister(); + + Debug::log(LOG, "Destroying workspace ID {}", m_iID); + + g_pEventManager->postEvent({"destroyworkspace", m_szName}); + EMIT_HOOK_EVENT("destroyWorkspace", this); +} + +void CWorkspace::startAnim(bool in, bool left, bool instant) { + const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle; + static auto* const PWORKSPACEGAP = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:gaps_workspaces"); + + if (ANIMSTYLE.starts_with("slidefade")) { + const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + float movePerc = 100.f; + + if (ANIMSTYLE.find("%") != std::string::npos) { + try { + auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' ') + 1); + movePerc = std::stoi(percstr.substr(0, percstr.length() - 1)); + } catch (std::exception& e) { Debug::log(ERR, "Error in startAnim: invalid percentage"); } + } + + m_fAlpha.setValueAndWarp(1.f); + m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); + + if (ANIMSTYLE.starts_with("slidefadevert")) { + if (in) { + m_fAlpha.setValueAndWarp(0.f); + m_vRenderOffset.setValueAndWarp(Vector2D(0, (left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y) * (movePerc / 100.f))); + m_fAlpha = 1.f; + m_vRenderOffset = Vector2D(0, 0); + } else { + m_fAlpha.setValueAndWarp(1.f); + m_fAlpha = 0.f; + m_vRenderOffset = Vector2D(0, (left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y) * (movePerc / 100.f)); + } + } else { + if (in) { + m_fAlpha.setValueAndWarp(0.f); + m_vRenderOffset.setValueAndWarp(Vector2D((left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x) * (movePerc / 100.f), 0)); + m_fAlpha = 1.f; + m_vRenderOffset = Vector2D(0, 0); + } else { + m_fAlpha.setValueAndWarp(1.f); + m_fAlpha = 0.f; + m_vRenderOffset = Vector2D((left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x) * (movePerc / 100.f), 0); + } + } + } else if (ANIMSTYLE == "fade") { + m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); // fix a bug, if switching from slide -> fade. + + if (in) { + m_fAlpha.setValueAndWarp(0.f); + m_fAlpha = 1.f; + } else { + m_fAlpha.setValueAndWarp(1.f); + m_fAlpha = 0.f; + } + } else if (ANIMSTYLE == "slidevert") { + // fallback is slide + const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto YDISTANCE = PMONITOR->vecSize.y + **PWORKSPACEGAP; + + m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. + + if (in) { + m_vRenderOffset.setValueAndWarp(Vector2D(0, left ? YDISTANCE : -YDISTANCE)); + m_vRenderOffset = Vector2D(0, 0); + } else { + m_vRenderOffset = Vector2D(0, left ? -YDISTANCE : YDISTANCE); + } + } else { + // fallback is slide + const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + const auto XDISTANCE = PMONITOR->vecSize.x + **PWORKSPACEGAP; + + m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. + + if (in) { + m_vRenderOffset.setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0)); + m_vRenderOffset = Vector2D(0, 0); + } else { + m_vRenderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0); + } + } + + if (m_bIsSpecialWorkspace) { + // required for open/close animations + if (in) { + m_fAlpha.setValueAndWarp(0.f); + m_fAlpha = 1.f; + } else { + m_fAlpha.setValueAndWarp(1.f); + m_fAlpha = 0.f; + } + } + + if (instant) { + m_vRenderOffset.warp(); + m_fAlpha.warp(); + } +} + +void CWorkspace::setActive(bool on) { + ; // empty until https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40 +} + +void CWorkspace::moveToMonitor(const int& id) { + ; // empty until https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40 +} + +CWindow* CWorkspace::getLastFocusedWindow() { + if (!g_pCompositor->windowValidMapped(m_pLastFocusedWindow) || m_pLastFocusedWindow->m_iWorkspaceID != m_iID) + return nullptr; + + return m_pLastFocusedWindow; +} + +void CWorkspace::rememberPrevWorkspace(const CWorkspace* prev) { + if (!prev) { + m_sPrevWorkspace.iID = -1; + m_sPrevWorkspace.name = ""; + return; + } + + if (prev->m_iID == m_iID) { + Debug::log(LOG, "Tried to set prev workspace to the same as current one"); + return; + } + + m_sPrevWorkspace.iID = prev->m_iID; + m_sPrevWorkspace.name = prev->m_szName; +} + +std::string CWorkspace::getConfigName() { + if (m_bIsSpecialWorkspace) { + return "special:" + m_szName; + } + + if (m_iID > 0) + return std::to_string(m_iID); + + return "name:" + m_szName; +} diff --git a/src/desktop/Workspace.hpp b/src/desktop/Workspace.hpp new file mode 100644 index 00000000..d4915769 --- /dev/null +++ b/src/desktop/Workspace.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include "../helpers/AnimatedVariable.hpp" +#include +#include "../defines.hpp" + +enum eFullscreenMode : int8_t { + FULLSCREEN_INVALID = -1, + FULLSCREEN_FULL = 0, + FULLSCREEN_MAXIMIZED +}; + +class CWindow; + +class CWorkspace { + public: + CWorkspace(int monitorID, std::string name, bool special = false); + ~CWorkspace(); + + // Workspaces ID-based have IDs > 0 + // and workspaces name-based have IDs starting with -1337 + int m_iID = -1; + std::string m_szName = ""; + uint64_t m_iMonitorID = -1; + // Previous workspace ID is stored during a workspace change, allowing travel + // to the previous workspace. + struct SPrevWorkspaceData { + int iID = -1; + std::string name = ""; + } m_sPrevWorkspace; + + bool m_bHasFullscreenWindow = false; + eFullscreenMode m_efFullscreenMode = FULLSCREEN_FULL; + + wl_array m_wlrCoordinateArr; + + // for animations + CAnimatedVariable m_vRenderOffset; + CAnimatedVariable m_fAlpha; + bool m_bForceRendering = false; + + // "scratchpad" + bool m_bIsSpecialWorkspace = false; + + // last window + CWindow* m_pLastFocusedWindow = nullptr; + + // user-set + bool m_bDefaultFloating = false; + bool m_bDefaultPseudo = false; + + // last monitor (used on reconnect) + std::string m_szLastMonitor = ""; + + // Whether the user configured command for on-created-empty has been executed, if any + bool m_bOnCreatedEmptyExecuted = false; + + void startAnim(bool in, bool left, bool instant = false); + void setActive(bool on); + + void moveToMonitor(const int&); + + CWindow* getLastFocusedWindow(); + void rememberPrevWorkspace(const CWorkspace* prevWorkspace); + + std::string getConfigName(); +}; diff --git a/src/helpers/Subsurface.cpp b/src/helpers/Subsurface.cpp deleted file mode 100644 index 0923e9cc..00000000 --- a/src/helpers/Subsurface.cpp +++ /dev/null @@ -1,238 +0,0 @@ -#include "Subsurface.hpp" -#include "../events/Events.hpp" -#include "../Compositor.hpp" - -static void onNewSubsurface(void* owner, void* data); - -CSubsurface::CSubsurface(CWindow* pOwner) : m_pWindowParent(pOwner) { - initSignals(); - - wlr_subsurface* wlrSubsurface; - wl_list_for_each(wlrSubsurface, &pOwner->m_pWLSurface.wlr()->current.subsurfaces_below, current.link) { - ::onNewSubsurface(this, wlrSubsurface); - } - wl_list_for_each(wlrSubsurface, &pOwner->m_pWLSurface.wlr()->current.subsurfaces_above, current.link) { - ::onNewSubsurface(this, wlrSubsurface); - } -} - -CSubsurface::CSubsurface(wlr_subsurface* pSubsurface, CWindow* pOwner) : m_pSubsurface(pSubsurface), m_pWindowParent(pOwner) { - m_sWLSurface.assign(pSubsurface->surface); - initSignals(); - initExistingSubsurfaces(); -} - -CSubsurface::~CSubsurface() { - hyprListener_newSubsurface.removeCallback(); - - if (!m_pSubsurface) - return; - - hyprListener_commitSubsurface.removeCallback(); - hyprListener_destroySubsurface.removeCallback(); - - const auto COORDS = coordsGlobal(); - - CBox box = {COORDS, m_vLastSize}; - g_pHyprRenderer->damageBox(&box); -} - -static void onNewSubsurface(void* owner, void* data) { - const auto PSUBSURFACE = (CSubsurface*)owner; - PSUBSURFACE->onNewSubsurface((wlr_subsurface*)data); -} - -static void onDestroySubsurface(void* owner, void* data) { - const auto PSUBSURFACE = (CSubsurface*)owner; - PSUBSURFACE->onDestroy(); -} - -static void onCommitSubsurface(void* owner, void* data) { - const auto PSUBSURFACE = (CSubsurface*)owner; - PSUBSURFACE->onCommit(); -} - -static void onMapSubsurface(void* owner, void* data) { - const auto PSUBSURFACE = (CSubsurface*)owner; - PSUBSURFACE->onMap(); -} - -static void onUnmapSubsurface(void* owner, void* data) { - const auto PSUBSURFACE = (CSubsurface*)owner; - PSUBSURFACE->onUnmap(); -} - -void CSubsurface::initSignals() { - if (m_pSubsurface) { - hyprListener_commitSubsurface.initCallback(&m_pSubsurface->surface->events.commit, &onCommitSubsurface, this, "CSubsurface"); - hyprListener_destroySubsurface.initCallback(&m_pSubsurface->events.destroy, &onDestroySubsurface, this, "CSubsurface"); - hyprListener_newSubsurface.initCallback(&m_pSubsurface->surface->events.new_subsurface, &::onNewSubsurface, this, "CSubsurface"); - hyprListener_mapSubsurface.initCallback(&m_pSubsurface->surface->events.map, &onMapSubsurface, this, "CSubsurface"); - hyprListener_newSubsurface.initCallback(&m_pSubsurface->surface->events.unmap, &onUnmapSubsurface, this, "CSubsurface"); - } else { - if (m_pWindowParent) - hyprListener_newSubsurface.initCallback(&m_pWindowParent->m_pWLSurface.wlr()->events.new_subsurface, &::onNewSubsurface, this, "CSubsurface"); - else - RASSERT(false, "CSubsurface::initSignals empty subsurface"); - } -} - -void CSubsurface::checkSiblingDamage() { - if (!m_pParent) - return; // ?????????? - - const double SCALE = m_pWindowParent && m_pWindowParent->m_bIsX11 ? 1.0 / m_pWindowParent->m_fX11SurfaceScaledBy : 1.0; - - for (auto& n : m_pParent->m_vChildren) { - if (n.get() == this) - continue; - - const auto COORDS = n->coordsGlobal(); - g_pHyprRenderer->damageSurface(n->m_sWLSurface.wlr(), COORDS.x, COORDS.y, SCALE); - } -} - -void CSubsurface::recheckDamageForSubsurfaces() { - const double SCALE = m_pWindowParent && m_pWindowParent->m_bIsX11 ? 1.0 / m_pWindowParent->m_fX11SurfaceScaledBy : 1.0; - - for (auto& n : m_vChildren) { - const auto COORDS = n->coordsGlobal(); - g_pHyprRenderer->damageSurface(n->m_sWLSurface.wlr(), COORDS.x, COORDS.y, SCALE); - } -} - -void CSubsurface::onCommit() { - // no damaging if it's not visible - if (!g_pHyprRenderer->shouldRenderWindow(m_pWindowParent)) { - m_vLastSize = Vector2D{m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}; - - static auto* const PLOGDAMAGE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("debug:log_damage"); - if (**PLOGDAMAGE) - Debug::log(LOG, "Refusing to commit damage from a subsurface of {} because it's invisible.", m_pWindowParent); - return; - } - - const auto COORDS = coordsGlobal(); - - const double SCALE = m_pWindowParent && m_pWindowParent->m_bIsX11 ? 1.0 / m_pWindowParent->m_fX11SurfaceScaledBy : 1.0; - - g_pHyprRenderer->damageSurface(m_sWLSurface.wlr(), COORDS.x, COORDS.y, SCALE); - - // I do not think this is correct, but it solves a lot of issues with some apps (e.g. firefox) - checkSiblingDamage(); - - if (m_vLastSize != Vector2D{m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}) { - CBox box{COORDS, m_vLastSize}; - g_pHyprRenderer->damageBox(&box); - m_vLastSize = Vector2D{m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}; - box = {COORDS, m_vLastSize}; - g_pHyprRenderer->damageBox(&box); - } - - if (m_pWindowParent) { - if (m_pWindowParent->m_bIsX11) - m_pWindowParent->m_vReportedSize = m_pWindowParent->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged. - - // tearing: if solitary, redraw it. This still might be a single surface window - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_pWindowParent->m_iMonitorID); - if (PMONITOR && PMONITOR->solitaryClient == m_pWindowParent && m_pWindowParent->canBeTorn() && PMONITOR->tearingState.canTear && - m_sWLSurface.wlr()->current.committed & WLR_SURFACE_STATE_BUFFER) { - CRegion damageBox{&m_sWLSurface.wlr()->buffer_damage}; - - if (!damageBox.empty()) { - if (PMONITOR->tearingState.busy) { - PMONITOR->tearingState.frameScheduledWhileBusy = true; - } else { - PMONITOR->tearingState.nextRenderTorn = true; - g_pHyprRenderer->renderMonitor(PMONITOR); - } - } - } - } -} - -void CSubsurface::onDestroy() { - // destroy children - m_vChildren.clear(); - - if (!m_pSubsurface) - return; // dummy node, nothing to do, it's the parent dying - - // kill ourselves - std::erase_if(m_pParent->m_vChildren, [this](const auto& other) { return other.get() == this; }); -} - -void CSubsurface::onNewSubsurface(wlr_subsurface* pSubsurface) { - CSubsurface* PSUBSURFACE = nullptr; - - if (m_pWindowParent) - PSUBSURFACE = m_vChildren.emplace_back(std::make_unique(pSubsurface, m_pWindowParent)).get(); - PSUBSURFACE->m_pParent = this; - - ASSERT(PSUBSURFACE); -} - -void CSubsurface::onMap() { - m_vLastSize = {m_sWLSurface.wlr()->current.width, m_sWLSurface.wlr()->current.height}; - - const auto COORDS = coordsGlobal(); - CBox box{COORDS, m_vLastSize}; - g_pHyprRenderer->damageBox(&box); - - if (m_pWindowParent) - m_pWindowParent->updateSurfaceScaleTransformDetails(); -} - -void CSubsurface::onUnmap() { - const auto COORDS = coordsGlobal(); - CBox box{COORDS, m_vLastSize}; - g_pHyprRenderer->damageBox(&box); - - if (m_sWLSurface.wlr() == g_pCompositor->m_pLastFocus) - g_pInputManager->releaseAllMouseButtons(); - - if (m_pWindowParent) - m_pWindowParent->updateSurfaceScaleTransformDetails(); - - g_pInputManager->simulateMouseMovement(); - - // TODO: should this remove children? Currently it won't, only on .destroy -} - -Vector2D CSubsurface::coordsRelativeToParent() { - Vector2D offset; - - CSubsurface* current = this; - - while (current->m_pParent) { - - offset += {current->m_sWLSurface.wlr()->current.dx, current->m_sWLSurface.wlr()->current.dy}; - offset += {current->m_pSubsurface->current.x, current->m_pSubsurface->current.y}; - - current = current->m_pParent; - } - - return offset; -} - -Vector2D CSubsurface::coordsGlobal() { - Vector2D coords = coordsRelativeToParent(); - - if (m_pWindowParent) - coords += m_pWindowParent->m_vRealPosition.vec(); - - return coords; -} - -void CSubsurface::initExistingSubsurfaces() { - if (m_pWindowParent) - return; - - wlr_subsurface* wlrSubsurface; - wl_list_for_each(wlrSubsurface, &m_sWLSurface.wlr()->current.subsurfaces_below, current.link) { - ::onNewSubsurface(this, wlrSubsurface); - } - wl_list_for_each(wlrSubsurface, &m_sWLSurface.wlr()->current.subsurfaces_above, current.link) { - ::onNewSubsurface(this, wlrSubsurface); - } -} \ No newline at end of file diff --git a/src/helpers/Subsurface.hpp b/src/helpers/Subsurface.hpp deleted file mode 100644 index a8f028af..00000000 --- a/src/helpers/Subsurface.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include "../defines.hpp" -#include -#include "WLSurface.hpp" - -class CWindow; - -class CSubsurface { - public: - // root dummy nodes - CSubsurface(CWindow* pOwner); - - // real nodes - CSubsurface(wlr_subsurface* pSubsurface, CWindow* pOwner); - - ~CSubsurface(); - - Vector2D coordsRelativeToParent(); - Vector2D coordsGlobal(); - - void onCommit(); - void onDestroy(); - void onNewSubsurface(wlr_subsurface* pSubsurface); - void onMap(); - void onUnmap(); - - void recheckDamageForSubsurfaces(); - - private: - DYNLISTENER(destroySubsurface); - DYNLISTENER(commitSubsurface); - DYNLISTENER(newSubsurface); - DYNLISTENER(mapSubsurface); - DYNLISTENER(unmapSubsurface); - - wlr_subsurface* m_pSubsurface = nullptr; - CWLSurface m_sWLSurface; - Vector2D m_vLastSize = {}; - - // if nullptr, means it's a dummy node - CSubsurface* m_pParent = nullptr; - - CWindow* m_pWindowParent = nullptr; - - std::vector> m_vChildren; - - void initSignals(); - void initExistingSubsurfaces(); - void checkSiblingDamage(); -}; \ No newline at end of file diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index c1110eaa..e536c3d2 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -4,9 +4,9 @@ #include "../defines.hpp" #include "wlr-layer-shell-unstable-v1-protocol.h" #include "../Window.hpp" -#include "Subsurface.hpp" +#include "../desktop/Subsurface.hpp" #include "AnimatedVariable.hpp" -#include "WLSurface.hpp" +#include "../desktop/WLSurface.hpp" #include "Region.hpp" struct SLayerRule { diff --git a/src/helpers/WLSurface.cpp b/src/helpers/WLSurface.cpp deleted file mode 100644 index 25f11feb..00000000 --- a/src/helpers/WLSurface.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#include "WLSurface.hpp" -#include "../Compositor.hpp" - -CWLSurface::CWLSurface(wlr_surface* pSurface) { - m_pWLRSurface = pSurface; - init(); -} - -void CWLSurface::assign(wlr_surface* pSurface) { - m_pWLRSurface = pSurface; - init(); -} - -void CWLSurface::unassign() { - destroy(); -} - -CWLSurface::~CWLSurface() { - destroy(); -} - -bool CWLSurface::exists() const { - return m_pWLRSurface; -} - -wlr_surface* CWLSurface::wlr() const { - return m_pWLRSurface; -} - -bool CWLSurface::small() const { - if (!m_pOwner || !exists()) - return false; - - return m_pOwner->m_vReportedSize.x > m_pWLRSurface->current.buffer_width + 1 || m_pOwner->m_vReportedSize.y > m_pWLRSurface->current.buffer_height + 1; -} - -Vector2D CWLSurface::correctSmallVec() const { - if (!m_pOwner || !exists() || !small() || m_bFillIgnoreSmall) - return {}; - - const auto SIZE = getViewporterCorrectedSize(); - - return Vector2D{(m_pOwner->m_vReportedSize.x - SIZE.x) / 2, (m_pOwner->m_vReportedSize.y - SIZE.y) / 2}.clamp({}, {INFINITY, INFINITY}) * - (m_pOwner->m_vRealSize.vec() / m_pOwner->m_vReportedSize); -} - -Vector2D CWLSurface::getViewporterCorrectedSize() const { - if (!exists()) - return {}; - - return m_pWLRSurface->current.viewport.has_dst ? Vector2D{m_pWLRSurface->current.viewport.dst_width, m_pWLRSurface->current.viewport.dst_height} : - Vector2D{m_pWLRSurface->current.buffer_width, m_pWLRSurface->current.buffer_height}; -} - -CRegion CWLSurface::logicalDamage() const { - CRegion damage{&m_pWLRSurface->buffer_damage}; - damage.transform(m_pWLRSurface->current.transform, m_pWLRSurface->current.buffer_width, m_pWLRSurface->current.buffer_height); - damage.scale(1.0 / m_pWLRSurface->current.scale); - - const auto VPSIZE = getViewporterCorrectedSize(); - const auto CORRECTVEC = correctSmallVec(); - - if (m_pWLRSurface->current.viewport.has_src) { - damage.intersect(CBox{std::floor(m_pWLRSurface->current.viewport.src.x), std::floor(m_pWLRSurface->current.viewport.src.y), - std::ceil(m_pWLRSurface->current.viewport.src.width), std::ceil(m_pWLRSurface->current.viewport.src.height)}); - } - - const auto SCALEDSRCSIZE = m_pWLRSurface->current.viewport.has_src ? - Vector2D{m_pWLRSurface->current.viewport.src.width, m_pWLRSurface->current.viewport.src.height} * m_pWLRSurface->current.scale : - Vector2D{m_pWLRSurface->current.buffer_width, m_pWLRSurface->current.buffer_height}; - - damage.scale({VPSIZE.x / SCALEDSRCSIZE.x, VPSIZE.y / SCALEDSRCSIZE.y}); - damage.translate(CORRECTVEC); - - return damage; -} - -void CWLSurface::destroy() { - if (!m_pWLRSurface) - return; - - hyprListener_destroy.removeCallback(); - m_pWLRSurface->data = nullptr; - m_pOwner = nullptr; - - if (g_pCompositor && g_pCompositor->m_pLastFocus == m_pWLRSurface) - g_pCompositor->m_pLastFocus = nullptr; - if (g_pInputManager && g_pInputManager->m_pLastMouseSurface == m_pWLRSurface) - g_pInputManager->m_pLastMouseSurface = nullptr; - if (g_pHyprRenderer && g_pHyprRenderer->m_sLastCursorData.surf == m_pWLRSurface) - g_pHyprRenderer->m_sLastCursorData.surf.reset(); - - m_pWLRSurface = nullptr; - - Debug::log(LOG, "CWLSurface {:x} called destroy()", (uintptr_t)this); -} - -void CWLSurface::init() { - if (!m_pWLRSurface) - return; - - RASSERT(!m_pWLRSurface->data, "Attempted to duplicate CWLSurface ownership!"); - - m_pWLRSurface->data = this; - - hyprListener_destroy.initCallback( - &m_pWLRSurface->events.destroy, [&](void* owner, void* data) { destroy(); }, this, "CWLSurface"); - - Debug::log(LOG, "CWLSurface {:x} called init()", (uintptr_t)this); -} \ No newline at end of file diff --git a/src/helpers/WLSurface.hpp b/src/helpers/WLSurface.hpp deleted file mode 100644 index eab4ac48..00000000 --- a/src/helpers/WLSurface.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once - -#include "../defines.hpp" -#include "Region.hpp" - -class CWindow; - -class CWLSurface { - public: - CWLSurface() = default; - CWLSurface(wlr_surface* pSurface); - ~CWLSurface(); - - void assign(wlr_surface* pSurface); - void unassign(); - - CWLSurface(const CWLSurface&) = delete; - CWLSurface(CWLSurface&&) = delete; - CWLSurface& operator=(const CWLSurface&) = delete; - CWLSurface& operator=(CWLSurface&&) = delete; - - wlr_surface* wlr() const; - bool exists() const; - bool small() const; // means surface is smaller than the requested size - Vector2D correctSmallVec() const; // returns a corrective vector for small() surfaces - Vector2D getViewporterCorrectedSize() const; - CRegion logicalDamage() const; - - // allow stretching. Useful for plugins. - bool m_bFillIgnoreSmall = false; - - // if present, means this is a base surface of a window. Cleaned on unassign() - CWindow* m_pOwner = nullptr; - - // track surface data and avoid dupes - float m_fLastScale = 0; - int m_iLastScale = 0; - wl_output_transform m_eLastTransform = (wl_output_transform)-1; - - // - CWLSurface& operator=(wlr_surface* pSurface) { - destroy(); - m_pWLRSurface = pSurface; - init(); - - return *this; - } - - bool operator==(const CWLSurface& other) const { - return other.wlr() == wlr(); - } - - bool operator==(const wlr_surface* other) const { - return other == wlr(); - } - - explicit operator bool() const { - return exists(); - } - - static CWLSurface* surfaceFromWlr(wlr_surface* pSurface) { - return (CWLSurface*)pSurface->data; - } - - private: - wlr_surface* m_pWLRSurface = nullptr; - - void destroy(); - void init(); - - DYNLISTENER(destroy); -}; \ No newline at end of file diff --git a/src/helpers/Workspace.cpp b/src/helpers/Workspace.cpp deleted file mode 100644 index ad8ae4ad..00000000 --- a/src/helpers/Workspace.cpp +++ /dev/null @@ -1,180 +0,0 @@ -#include "Workspace.hpp" -#include "../Compositor.hpp" - -CWorkspace::CWorkspace(int monitorID, std::string name, bool special) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(monitorID); - - if (!PMONITOR) { - Debug::log(ERR, "Attempted a creation of CWorkspace with an invalid monitor?"); - return; - } - - m_iMonitorID = monitorID; - m_szName = name; - m_bIsSpecialWorkspace = special; - - m_vRenderOffset.m_pWorkspace = this; - m_vRenderOffset.create(AVARTYPE_VECTOR, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), - nullptr, AVARDAMAGE_ENTIRE); - m_fAlpha.m_pWorkspace = this; - m_fAlpha.create(AVARTYPE_FLOAT, special ? g_pConfigManager->getAnimationPropertyConfig("specialWorkspace") : g_pConfigManager->getAnimationPropertyConfig("workspaces"), - nullptr, AVARDAMAGE_ENTIRE); - m_fAlpha.setValueAndWarp(1.f); - - m_vRenderOffset.registerVar(); - m_fAlpha.registerVar(); - - const auto RULEFORTHIS = g_pConfigManager->getWorkspaceRuleFor(this); - if (RULEFORTHIS.defaultName.has_value()) - m_szName = RULEFORTHIS.defaultName.value(); - - g_pEventManager->postEvent({"createworkspace", m_szName}); - EMIT_HOOK_EVENT("createWorkspace", this); -} - -CWorkspace::~CWorkspace() { - m_vRenderOffset.unregister(); - - Debug::log(LOG, "Destroying workspace ID {}", m_iID); - - g_pEventManager->postEvent({"destroyworkspace", m_szName}); - EMIT_HOOK_EVENT("destroyWorkspace", this); -} - -void CWorkspace::startAnim(bool in, bool left, bool instant) { - const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle; - static auto* const PWORKSPACEGAP = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:gaps_workspaces"); - - if (ANIMSTYLE.starts_with("slidefade")) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); - float movePerc = 100.f; - - if (ANIMSTYLE.find("%") != std::string::npos) { - try { - auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' ') + 1); - movePerc = std::stoi(percstr.substr(0, percstr.length() - 1)); - } catch (std::exception& e) { Debug::log(ERR, "Error in startAnim: invalid percentage"); } - } - - m_fAlpha.setValueAndWarp(1.f); - m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); - - if (ANIMSTYLE.starts_with("slidefadevert")) { - if (in) { - m_fAlpha.setValueAndWarp(0.f); - m_vRenderOffset.setValueAndWarp(Vector2D(0, (left ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y) * (movePerc / 100.f))); - m_fAlpha = 1.f; - m_vRenderOffset = Vector2D(0, 0); - } else { - m_fAlpha.setValueAndWarp(1.f); - m_fAlpha = 0.f; - m_vRenderOffset = Vector2D(0, (left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y) * (movePerc / 100.f)); - } - } else { - if (in) { - m_fAlpha.setValueAndWarp(0.f); - m_vRenderOffset.setValueAndWarp(Vector2D((left ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x) * (movePerc / 100.f), 0)); - m_fAlpha = 1.f; - m_vRenderOffset = Vector2D(0, 0); - } else { - m_fAlpha.setValueAndWarp(1.f); - m_fAlpha = 0.f; - m_vRenderOffset = Vector2D((left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x) * (movePerc / 100.f), 0); - } - } - } else if (ANIMSTYLE == "fade") { - m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); // fix a bug, if switching from slide -> fade. - - if (in) { - m_fAlpha.setValueAndWarp(0.f); - m_fAlpha = 1.f; - } else { - m_fAlpha.setValueAndWarp(1.f); - m_fAlpha = 0.f; - } - } else if (ANIMSTYLE == "slidevert") { - // fallback is slide - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); - const auto YDISTANCE = PMONITOR->vecSize.y + **PWORKSPACEGAP; - - m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. - - if (in) { - m_vRenderOffset.setValueAndWarp(Vector2D(0, left ? YDISTANCE : -YDISTANCE)); - m_vRenderOffset = Vector2D(0, 0); - } else { - m_vRenderOffset = Vector2D(0, left ? -YDISTANCE : YDISTANCE); - } - } else { - // fallback is slide - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); - const auto XDISTANCE = PMONITOR->vecSize.x + **PWORKSPACEGAP; - - m_fAlpha.setValueAndWarp(1.f); // fix a bug, if switching from fade -> slide. - - if (in) { - m_vRenderOffset.setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0)); - m_vRenderOffset = Vector2D(0, 0); - } else { - m_vRenderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0); - } - } - - if (m_bIsSpecialWorkspace) { - // required for open/close animations - if (in) { - m_fAlpha.setValueAndWarp(0.f); - m_fAlpha = 1.f; - } else { - m_fAlpha.setValueAndWarp(1.f); - m_fAlpha = 0.f; - } - } - - if (instant) { - m_vRenderOffset.warp(); - m_fAlpha.warp(); - } -} - -void CWorkspace::setActive(bool on) { - ; // empty until https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40 -} - -void CWorkspace::moveToMonitor(const int& id) { - ; // empty until https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/40 -} - -CWindow* CWorkspace::getLastFocusedWindow() { - if (!g_pCompositor->windowValidMapped(m_pLastFocusedWindow) || m_pLastFocusedWindow->m_iWorkspaceID != m_iID) - return nullptr; - - return m_pLastFocusedWindow; -} - -void CWorkspace::rememberPrevWorkspace(const CWorkspace* prev) { - if (!prev) { - m_sPrevWorkspace.iID = -1; - m_sPrevWorkspace.name = ""; - return; - } - - if (prev->m_iID == m_iID) { - Debug::log(LOG, "Tried to set prev workspace to the same as current one"); - return; - } - - m_sPrevWorkspace.iID = prev->m_iID; - m_sPrevWorkspace.name = prev->m_szName; -} - -std::string CWorkspace::getConfigName() { - if (m_bIsSpecialWorkspace) { - return "special:" + m_szName; - } - - if (m_iID > 0) - return std::to_string(m_iID); - - return "name:" + m_szName; -} diff --git a/src/helpers/Workspace.hpp b/src/helpers/Workspace.hpp deleted file mode 100644 index a0bbb815..00000000 --- a/src/helpers/Workspace.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -#include "AnimatedVariable.hpp" -#include -#include "../defines.hpp" - -enum eFullscreenMode : int8_t { - FULLSCREEN_INVALID = -1, - FULLSCREEN_FULL = 0, - FULLSCREEN_MAXIMIZED -}; - -class CWindow; - -class CWorkspace { - public: - CWorkspace(int monitorID, std::string name, bool special = false); - ~CWorkspace(); - - // Workspaces ID-based have IDs > 0 - // and workspaces name-based have IDs starting with -1337 - int m_iID = -1; - std::string m_szName = ""; - uint64_t m_iMonitorID = -1; - // Previous workspace ID is stored during a workspace change, allowing travel - // to the previous workspace. - struct SPrevWorkspaceData { - int iID = -1; - std::string name = ""; - } m_sPrevWorkspace; - - bool m_bHasFullscreenWindow = false; - eFullscreenMode m_efFullscreenMode = FULLSCREEN_FULL; - - wl_array m_wlrCoordinateArr; - - // for animations - CAnimatedVariable m_vRenderOffset; - CAnimatedVariable m_fAlpha; - bool m_bForceRendering = false; - - // "scratchpad" - bool m_bIsSpecialWorkspace = false; - - // last window - CWindow* m_pLastFocusedWindow = nullptr; - - // user-set - bool m_bDefaultFloating = false; - bool m_bDefaultPseudo = false; - - // last monitor (used on reconnect) - std::string m_szLastMonitor = ""; - - // Whether the user configured command for on-created-empty has been executed, if any - bool m_bOnCreatedEmptyExecuted = false; - - void startAnim(bool in, bool left, bool instant = false); - void setActive(bool on); - - void moveToMonitor(const int&); - - CWindow* getLastFocusedWindow(); - void rememberPrevWorkspace(const CWorkspace* prevWorkspace); - - std::string getConfigName(); -}; diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 5eafb639..53cace82 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -3,7 +3,6 @@ #include "../defines.hpp" #include #include "../helpers/Monitor.hpp" -#include "../helpers/Workspace.hpp" #include "../Window.hpp" #include "OpenGL.hpp" #include "Renderbuffer.hpp" @@ -11,6 +10,7 @@ #include "../helpers/Region.hpp" struct SMonitorRule; +class CWorkspace; // TODO: add fuller damage tracking for updating only parts of a window enum DAMAGETRACKINGMODES { -- cgit v1.2.3