2024-05-28 23:37:24 +02:00
|
|
|
#include <any>
|
|
|
|
#include <string_view>
|
|
|
|
#include <algorithm>
|
2022-03-30 21:18:42 +02:00
|
|
|
#include "Window.hpp"
|
2024-03-20 02:44:51 +01:00
|
|
|
#include "../Compositor.hpp"
|
|
|
|
#include "../render/decorations/CHyprDropShadowDecoration.hpp"
|
|
|
|
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
|
|
|
#include "../render/decorations/CHyprBorderDecoration.hpp"
|
|
|
|
#include "../config/ConfigValue.hpp"
|
2024-04-23 02:28:20 +02:00
|
|
|
#include "../managers/TokenManager.hpp"
|
2024-05-11 00:28:33 +02:00
|
|
|
#include "../protocols/XDGShell.hpp"
|
2024-06-08 10:07:59 +02:00
|
|
|
#include "../protocols/core/Compositor.hpp"
|
2024-05-25 22:43:51 +02:00
|
|
|
#include "../xwayland/XWayland.hpp"
|
2022-03-30 21:18:42 +02:00
|
|
|
|
2024-06-11 17:17:45 +02:00
|
|
|
#include <hyprutils/string/String.hpp>
|
|
|
|
using namespace Hyprutils::String;
|
|
|
|
|
2024-05-25 22:43:51 +02:00
|
|
|
PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
|
|
|
|
PHLWINDOW pWindow = SP<CWindow>(new CWindow(surface));
|
2024-04-27 13:43:12 +02:00
|
|
|
|
2024-05-25 22:43:51 +02:00
|
|
|
pWindow->m_pSelf = pWindow;
|
|
|
|
pWindow->m_bIsX11 = true;
|
|
|
|
pWindow->m_iX11Type = surface->overrideRedirect ? 2 : 1;
|
2024-04-27 13:43:12 +02:00
|
|
|
|
|
|
|
pWindow->m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
|
|
|
|
pWindow->m_vRealSize.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
|
|
|
|
pWindow->m_fBorderFadeAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("border"), pWindow, AVARDAMAGE_BORDER);
|
|
|
|
pWindow->m_fBorderAngleAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("borderangle"), pWindow, AVARDAMAGE_BORDER);
|
|
|
|
pWindow->m_fAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE);
|
|
|
|
pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE);
|
|
|
|
pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW);
|
|
|
|
pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE);
|
|
|
|
|
|
|
|
pWindow->addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(pWindow));
|
|
|
|
pWindow->addWindowDeco(std::make_unique<CHyprBorderDecoration>(pWindow));
|
2022-06-25 20:28:40 +02:00
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
return pWindow;
|
|
|
|
}
|
|
|
|
|
2024-05-11 00:28:33 +02:00
|
|
|
PHLWINDOW CWindow::create(SP<CXDGSurfaceResource> resource) {
|
|
|
|
PHLWINDOW pWindow = SP<CWindow>(new CWindow(resource));
|
|
|
|
|
|
|
|
pWindow->m_pSelf = pWindow;
|
|
|
|
resource->toplevel->window = pWindow;
|
|
|
|
|
|
|
|
pWindow->m_vRealPosition.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
|
|
|
|
pWindow->m_vRealSize.create(g_pConfigManager->getAnimationPropertyConfig("windowsIn"), pWindow, AVARDAMAGE_ENTIRE);
|
|
|
|
pWindow->m_fBorderFadeAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("border"), pWindow, AVARDAMAGE_BORDER);
|
|
|
|
pWindow->m_fBorderAngleAnimationProgress.create(g_pConfigManager->getAnimationPropertyConfig("borderangle"), pWindow, AVARDAMAGE_BORDER);
|
|
|
|
pWindow->m_fAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeIn"), pWindow, AVARDAMAGE_ENTIRE);
|
|
|
|
pWindow->m_fActiveInactiveAlpha.create(g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), pWindow, AVARDAMAGE_ENTIRE);
|
|
|
|
pWindow->m_cRealShadowColor.create(g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), pWindow, AVARDAMAGE_SHADOW);
|
|
|
|
pWindow->m_fDimPercent.create(g_pConfigManager->getAnimationPropertyConfig("fadeDim"), pWindow, AVARDAMAGE_ENTIRE);
|
|
|
|
|
|
|
|
pWindow->addWindowDeco(std::make_unique<CHyprDropShadowDecoration>(pWindow));
|
|
|
|
pWindow->addWindowDeco(std::make_unique<CHyprBorderDecoration>(pWindow));
|
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
pWindow->m_pWLSurface->assign(pWindow->m_pXDGSurface->surface.lock(), pWindow);
|
2024-05-11 00:28:33 +02:00
|
|
|
|
|
|
|
return pWindow;
|
|
|
|
}
|
|
|
|
|
|
|
|
CWindow::CWindow(SP<CXDGSurfaceResource> resource) : m_pXDGSurface(resource) {
|
2024-06-08 10:07:59 +02:00
|
|
|
m_pWLSurface = CWLSurface::create();
|
|
|
|
|
2024-05-11 00:28:33 +02:00
|
|
|
listeners.map = m_pXDGSurface->events.map.registerListener([this](std::any d) { Events::listener_mapWindow(this, nullptr); });
|
|
|
|
listeners.ack = m_pXDGSurface->events.ack.registerListener([this](std::any d) { onAck(std::any_cast<uint32_t>(d)); });
|
|
|
|
listeners.unmap = m_pXDGSurface->events.unmap.registerListener([this](std::any d) { Events::listener_unmapWindow(this, nullptr); });
|
|
|
|
listeners.destroy = m_pXDGSurface->events.destroy.registerListener([this](std::any d) { Events::listener_destroyWindow(this, nullptr); });
|
|
|
|
listeners.commit = m_pXDGSurface->events.commit.registerListener([this](std::any d) { Events::listener_commitWindow(this, nullptr); });
|
|
|
|
listeners.updateState = m_pXDGSurface->toplevel->events.stateChanged.registerListener([this](std::any d) { onUpdateState(); });
|
|
|
|
listeners.updateMetadata = m_pXDGSurface->toplevel->events.metadataChanged.registerListener([this](std::any d) { onUpdateMeta(); });
|
|
|
|
}
|
|
|
|
|
2024-05-25 22:43:51 +02:00
|
|
|
CWindow::CWindow(SP<CXWaylandSurface> surface) : m_pXWaylandSurface(surface) {
|
2024-06-08 10:07:59 +02:00
|
|
|
m_pWLSurface = CWLSurface::create();
|
|
|
|
|
2024-05-25 22:43:51 +02:00
|
|
|
listeners.map = m_pXWaylandSurface->events.map.registerListener([this](std::any d) { Events::listener_mapWindow(this, nullptr); });
|
|
|
|
listeners.unmap = m_pXWaylandSurface->events.unmap.registerListener([this](std::any d) { Events::listener_unmapWindow(this, nullptr); });
|
|
|
|
listeners.destroy = m_pXWaylandSurface->events.destroy.registerListener([this](std::any d) { Events::listener_destroyWindow(this, nullptr); });
|
|
|
|
listeners.commit = m_pXWaylandSurface->events.commit.registerListener([this](std::any d) { Events::listener_commitWindow(this, nullptr); });
|
|
|
|
listeners.configure = m_pXWaylandSurface->events.configure.registerListener([this](std::any d) { onX11Configure(std::any_cast<CBox>(d)); });
|
|
|
|
listeners.updateState = m_pXWaylandSurface->events.stateChanged.registerListener([this](std::any d) { onUpdateState(); });
|
|
|
|
listeners.updateMetadata = m_pXWaylandSurface->events.metadataChanged.registerListener([this](std::any d) { onUpdateMeta(); });
|
|
|
|
listeners.resourceChange = m_pXWaylandSurface->events.resourceChange.registerListener([this](std::any d) { onResourceChangeX11(); });
|
|
|
|
listeners.activate = m_pXWaylandSurface->events.activate.registerListener([this](std::any d) { Events::listener_activateX11(this, nullptr); });
|
|
|
|
|
|
|
|
if (m_pXWaylandSurface->overrideRedirect)
|
|
|
|
listeners.setGeometry = m_pXWaylandSurface->events.setGeometry.registerListener([this](std::any d) { Events::listener_unmanagedSetGeometry(this, nullptr); });
|
2022-04-23 14:16:02 +02:00
|
|
|
}
|
|
|
|
|
2022-03-30 21:18:42 +02:00
|
|
|
CWindow::~CWindow() {
|
2024-04-27 13:43:12 +02:00
|
|
|
if (g_pCompositor->m_pLastWindow.lock().get() == this) {
|
2024-06-08 10:07:59 +02:00
|
|
|
g_pCompositor->m_pLastFocus.reset();
|
2024-04-27 13:43:12 +02:00
|
|
|
g_pCompositor->m_pLastWindow.reset();
|
2022-04-02 18:57:09 +02:00
|
|
|
}
|
2023-12-04 02:44:06 +01:00
|
|
|
|
2024-04-21 17:28:50 +02:00
|
|
|
events.destroy.emit();
|
|
|
|
|
2023-12-06 15:46:18 +01:00
|
|
|
if (!g_pHyprOpenGL)
|
|
|
|
return;
|
|
|
|
|
2023-12-04 02:44:06 +01:00
|
|
|
g_pHyprRenderer->makeEGLCurrent();
|
2024-04-27 13:43:12 +02:00
|
|
|
std::erase_if(g_pHyprOpenGL->m_mWindowFramebuffers, [&](const auto& other) { return !other.first.lock() || other.first.lock().get() == this; });
|
2022-05-30 14:55:42 +02:00
|
|
|
}
|
|
|
|
|
2024-06-19 16:20:06 +02:00
|
|
|
SBoxExtents CWindow::getFullWindowExtents() {
|
2023-08-09 14:28:04 +02:00
|
|
|
if (m_bFadingOut)
|
|
|
|
return m_eOriginalClosedExtents;
|
|
|
|
|
2023-08-17 10:13:19 +02:00
|
|
|
const int BORDERSIZE = getRealBorderSize();
|
2023-07-23 15:49:49 +02:00
|
|
|
|
2024-07-11 16:10:42 +02:00
|
|
|
if (m_sWindowData.dimAround.valueOrDefault()) {
|
2024-05-22 22:37:02 +02:00
|
|
|
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR)
|
|
|
|
return {{m_vRealPosition.value().x - PMONITOR->vecPosition.x, m_vRealPosition.value().y - PMONITOR->vecPosition.y},
|
|
|
|
{PMONITOR->vecSize.x - (m_vRealPosition.value().x - PMONITOR->vecPosition.x), PMONITOR->vecSize.y - (m_vRealPosition.value().y - PMONITOR->vecPosition.y)}};
|
2022-12-31 19:23:02 +01:00
|
|
|
}
|
2022-05-30 14:55:42 +02:00
|
|
|
|
2024-06-19 16:20:06 +02:00
|
|
|
SBoxExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}};
|
2022-05-30 14:55:42 +02:00
|
|
|
|
2024-06-19 16:20:06 +02:00
|
|
|
const auto EXTENTS = g_pDecorationPositioner->getWindowDecorationExtents(m_pSelf.lock());
|
2022-05-30 14:55:42 +02:00
|
|
|
|
2023-11-11 15:37:17 +01:00
|
|
|
if (EXTENTS.topLeft.x > maxExtents.topLeft.x)
|
|
|
|
maxExtents.topLeft.x = EXTENTS.topLeft.x;
|
2022-05-30 14:55:42 +02:00
|
|
|
|
2023-11-11 15:37:17 +01:00
|
|
|
if (EXTENTS.topLeft.y > maxExtents.topLeft.y)
|
|
|
|
maxExtents.topLeft.y = EXTENTS.topLeft.y;
|
2022-05-30 14:55:42 +02:00
|
|
|
|
2023-11-11 15:37:17 +01:00
|
|
|
if (EXTENTS.bottomRight.x > maxExtents.bottomRight.x)
|
|
|
|
maxExtents.bottomRight.x = EXTENTS.bottomRight.x;
|
2022-05-30 14:55:42 +02:00
|
|
|
|
2023-11-11 15:37:17 +01:00
|
|
|
if (EXTENTS.bottomRight.y > maxExtents.bottomRight.y)
|
|
|
|
maxExtents.bottomRight.y = EXTENTS.bottomRight.y;
|
2022-05-30 14:55:42 +02:00
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
if (m_pWLSurface->exists() && !m_bIsX11 && m_pPopupHead) {
|
2023-11-04 18:03:05 +01:00
|
|
|
CBox surfaceExtents = {0, 0, 0, 0};
|
2023-06-23 13:54:01 +02:00
|
|
|
// TODO: this could be better, perhaps make a getFullWindowRegion?
|
2024-05-11 00:28:33 +02:00
|
|
|
m_pPopupHead->breadthfirst(
|
|
|
|
[](CPopup* popup, void* data) {
|
2024-06-08 10:07:59 +02:00
|
|
|
if (!popup->m_pWLSurface || !popup->m_pWLSurface->resource())
|
2024-05-11 00:28:33 +02:00
|
|
|
return;
|
|
|
|
|
2023-11-04 18:03:05 +01:00
|
|
|
CBox* pSurfaceExtents = (CBox*)data;
|
2024-05-11 00:28:33 +02:00
|
|
|
CBox surf = CBox{popup->coordsRelativeToParent(), popup->size()};
|
|
|
|
if (surf.x < pSurfaceExtents->x)
|
|
|
|
pSurfaceExtents->x = surf.x;
|
|
|
|
if (surf.y < pSurfaceExtents->y)
|
|
|
|
pSurfaceExtents->y = surf.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;
|
2023-06-23 13:54:01 +02:00
|
|
|
},
|
|
|
|
&surfaceExtents);
|
|
|
|
|
|
|
|
if (-surfaceExtents.x > maxExtents.topLeft.x)
|
|
|
|
maxExtents.topLeft.x = -surfaceExtents.x;
|
|
|
|
|
|
|
|
if (-surfaceExtents.y > maxExtents.topLeft.y)
|
|
|
|
maxExtents.topLeft.y = -surfaceExtents.y;
|
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
if (surfaceExtents.x + surfaceExtents.width > m_pWLSurface->resource()->current.size.x + maxExtents.bottomRight.x)
|
|
|
|
maxExtents.bottomRight.x = surfaceExtents.x + surfaceExtents.width - m_pWLSurface->resource()->current.size.x;
|
2023-06-23 13:54:01 +02:00
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
if (surfaceExtents.y + surfaceExtents.height > m_pWLSurface->resource()->current.size.y + maxExtents.bottomRight.y)
|
|
|
|
maxExtents.bottomRight.y = surfaceExtents.y + surfaceExtents.height - m_pWLSurface->resource()->current.size.y;
|
2023-06-23 13:54:01 +02:00
|
|
|
}
|
|
|
|
|
2023-08-09 14:28:04 +02:00
|
|
|
return maxExtents;
|
|
|
|
}
|
|
|
|
|
2023-11-04 18:03:05 +01:00
|
|
|
CBox CWindow::getFullWindowBoundingBox() {
|
2024-07-11 16:10:42 +02:00
|
|
|
if (m_sWindowData.dimAround.valueOrDefault()) {
|
2024-05-22 22:37:02 +02:00
|
|
|
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR)
|
|
|
|
return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
2023-08-09 14:28:04 +02:00
|
|
|
}
|
|
|
|
|
2023-11-04 18:03:05 +01:00
|
|
|
auto maxExtents = getFullWindowExtents();
|
2023-08-09 14:28:04 +02:00
|
|
|
|
2024-03-02 01:35:17 +01:00
|
|
|
CBox finalBox = {m_vRealPosition.value().x - maxExtents.topLeft.x, m_vRealPosition.value().y - maxExtents.topLeft.y,
|
|
|
|
m_vRealSize.value().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.value().y + maxExtents.topLeft.y + maxExtents.bottomRight.y};
|
2022-09-25 20:07:48 +02:00
|
|
|
|
2022-05-30 14:55:42 +02:00
|
|
|
return finalBox;
|
2022-06-23 20:39:48 +02:00
|
|
|
}
|
|
|
|
|
2023-11-04 18:03:05 +01:00
|
|
|
CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
2022-06-23 20:39:48 +02:00
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
|
|
|
|
2024-06-03 21:09:18 +02:00
|
|
|
if (!PMONITOR)
|
|
|
|
return {m_vPosition, m_vSize};
|
|
|
|
|
|
|
|
auto POS = m_vPosition;
|
|
|
|
auto SIZE = m_vSize;
|
2022-06-23 20:39:48 +02:00
|
|
|
|
2022-11-22 00:33:23 +01:00
|
|
|
if (m_bIsFullscreen) {
|
2022-12-16 18:17:31 +01:00
|
|
|
POS = PMONITOR->vecPosition;
|
2022-11-22 00:33:23 +01:00
|
|
|
SIZE = PMONITOR->vecSize;
|
|
|
|
|
2023-11-04 18:03:05 +01:00
|
|
|
return CBox{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
2022-11-22 00:33:23 +01:00
|
|
|
}
|
|
|
|
|
2022-06-23 20:39:48 +02:00
|
|
|
if (DELTALESSTHAN(POS.y - PMONITOR->vecPosition.y, PMONITOR->vecReservedTopLeft.y, 1)) {
|
|
|
|
POS.y = PMONITOR->vecPosition.y;
|
|
|
|
SIZE.y += PMONITOR->vecReservedTopLeft.y;
|
|
|
|
}
|
|
|
|
if (DELTALESSTHAN(POS.x - PMONITOR->vecPosition.x, PMONITOR->vecReservedTopLeft.x, 1)) {
|
|
|
|
POS.x = PMONITOR->vecPosition.x;
|
|
|
|
SIZE.x += PMONITOR->vecReservedTopLeft.x;
|
|
|
|
}
|
|
|
|
if (DELTALESSTHAN(POS.x + SIZE.x - PMONITOR->vecPosition.x, PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x, 1)) {
|
|
|
|
SIZE.x += PMONITOR->vecReservedBottomRight.x;
|
|
|
|
}
|
|
|
|
if (DELTALESSTHAN(POS.y + SIZE.y - PMONITOR->vecPosition.y, PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y, 1)) {
|
|
|
|
SIZE.y += PMONITOR->vecReservedBottomRight.y;
|
|
|
|
}
|
|
|
|
|
2023-11-04 18:03:05 +01:00
|
|
|
return CBox{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y};
|
2022-06-27 00:25:37 +02:00
|
|
|
}
|
|
|
|
|
2024-02-04 16:40:20 +01:00
|
|
|
CBox CWindow::getWindowBoxUnified(uint64_t properties) {
|
2024-07-11 16:10:42 +02:00
|
|
|
if (m_sWindowData.dimAround.valueOrDefault()) {
|
2023-02-28 23:32:42 +01:00
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
2024-06-03 21:09:18 +02:00
|
|
|
if (PMONITOR)
|
|
|
|
return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y};
|
2023-02-28 23:32:42 +01:00
|
|
|
}
|
|
|
|
|
2024-06-19 16:20:06 +02:00
|
|
|
SBoxExtents EXTENTS = {{0, 0}, {0, 0}};
|
2024-02-04 16:40:20 +01:00
|
|
|
if (properties & RESERVED_EXTENTS)
|
2024-04-27 13:43:12 +02:00
|
|
|
EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationReserved(m_pSelf.lock()));
|
2024-02-04 16:40:20 +01:00
|
|
|
if (properties & INPUT_EXTENTS)
|
2024-04-27 13:43:12 +02:00
|
|
|
EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationExtents(m_pSelf.lock(), true));
|
2024-02-04 16:40:20 +01:00
|
|
|
if (properties & FULL_EXTENTS)
|
2024-04-27 13:43:12 +02:00
|
|
|
EXTENTS.addExtents(g_pDecorationPositioner->getWindowDecorationExtents(m_pSelf.lock(), false));
|
2023-02-28 23:32:42 +01:00
|
|
|
|
2024-03-02 01:35:17 +01:00
|
|
|
CBox box = {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y};
|
2024-02-04 16:40:20 +01:00
|
|
|
box.addExtents(EXTENTS);
|
2023-02-28 23:32:42 +01:00
|
|
|
|
2024-02-04 16:40:20 +01:00
|
|
|
return box;
|
2023-02-28 23:32:42 +01:00
|
|
|
}
|
|
|
|
|
2023-11-04 18:03:05 +01:00
|
|
|
CBox CWindow::getWindowMainSurfaceBox() {
|
2024-03-02 01:35:17 +01:00
|
|
|
return {m_vRealPosition.value().x, m_vRealPosition.value().y, m_vRealSize.value().x, m_vRealSize.value().y};
|
2023-10-29 19:09:05 +01:00
|
|
|
}
|
|
|
|
|
2024-06-19 16:20:06 +02:00
|
|
|
SBoxExtents CWindow::getFullWindowReservedArea() {
|
2024-04-27 13:43:12 +02:00
|
|
|
return g_pDecorationPositioner->getWindowDecorationReserved(m_pSelf.lock());
|
2023-02-28 20:36:36 +01:00
|
|
|
}
|
|
|
|
|
2022-06-27 00:25:37 +02:00
|
|
|
void CWindow::updateWindowDecos() {
|
2023-06-05 09:49:17 +02:00
|
|
|
|
2023-11-11 15:37:17 +01:00
|
|
|
if (!m_bIsMapped || isHidden())
|
|
|
|
return;
|
|
|
|
|
2022-07-05 17:31:47 +02:00
|
|
|
for (auto& wd : m_vDecosToRemove) {
|
|
|
|
for (auto it = m_dWindowDecorations.begin(); it != m_dWindowDecorations.end(); it++) {
|
|
|
|
if (it->get() == wd) {
|
2023-11-11 15:37:17 +01:00
|
|
|
g_pDecorationPositioner->uncacheDecoration(it->get());
|
2024-05-01 13:59:40 +02:00
|
|
|
it = m_dWindowDecorations.erase(it);
|
2022-07-05 17:31:47 +02:00
|
|
|
if (it == m_dWindowDecorations.end())
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
g_pDecorationPositioner->onWindowUpdate(m_pSelf.lock());
|
2023-11-11 15:37:17 +01:00
|
|
|
|
2022-07-05 17:31:47 +02:00
|
|
|
m_vDecosToRemove.clear();
|
2023-11-11 15:37:17 +01:00
|
|
|
|
2024-03-10 17:56:32 +01:00
|
|
|
// make a copy because updateWindow can remove decos.
|
|
|
|
std::vector<IHyprWindowDecoration*> decos;
|
|
|
|
|
2023-11-11 15:37:17 +01:00
|
|
|
for (auto& wd : m_dWindowDecorations) {
|
2024-03-10 17:56:32 +01:00
|
|
|
decos.push_back(wd.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto& wd : decos) {
|
2024-05-07 17:50:30 +02:00
|
|
|
if (std::find_if(m_dWindowDecorations.begin(), m_dWindowDecorations.end(), [wd](const auto& other) { return other.get() == wd; }) == m_dWindowDecorations.end())
|
|
|
|
continue;
|
2024-04-27 13:43:12 +02:00
|
|
|
wd->updateWindow(m_pSelf.lock());
|
2023-11-11 15:37:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CWindow::addWindowDeco(std::unique_ptr<IHyprWindowDecoration> deco) {
|
|
|
|
m_dWindowDecorations.emplace_back(std::move(deco));
|
2024-04-27 13:43:12 +02:00
|
|
|
g_pDecorationPositioner->forceRecalcFor(m_pSelf.lock());
|
2023-11-11 15:37:17 +01:00
|
|
|
updateWindowDecos();
|
2024-04-27 13:43:12 +02:00
|
|
|
g_pLayoutManager->getCurrentLayout()->recalculateWindow(m_pSelf.lock());
|
2023-11-11 15:37:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CWindow::removeWindowDeco(IHyprWindowDecoration* deco) {
|
|
|
|
m_vDecosToRemove.push_back(deco);
|
2024-04-27 13:43:12 +02:00
|
|
|
g_pDecorationPositioner->forceRecalcFor(m_pSelf.lock());
|
2023-11-11 15:37:17 +01:00
|
|
|
updateWindowDecos();
|
2024-04-27 13:43:12 +02:00
|
|
|
g_pLayoutManager->getCurrentLayout()->recalculateWindow(m_pSelf.lock());
|
2022-06-27 13:42:20 +02:00
|
|
|
}
|
|
|
|
|
2023-12-30 15:18:53 +01:00
|
|
|
void CWindow::uncacheWindowDecos() {
|
|
|
|
for (auto& wd : m_dWindowDecorations) {
|
|
|
|
g_pDecorationPositioner->uncacheDecoration(wd.get());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-28 23:54:41 +01:00
|
|
|
bool CWindow::checkInputOnDecos(const eInputType type, const Vector2D& mouseCoords, std::any data) {
|
|
|
|
if (type != INPUT_TYPE_DRAG_END && hasPopupAt(mouseCoords))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (auto& wd : m_dWindowDecorations) {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-06-27 13:42:20 +02:00
|
|
|
pid_t CWindow::getPID() {
|
|
|
|
pid_t PID = -1;
|
|
|
|
if (!m_bIsX11) {
|
2024-05-11 00:28:33 +02:00
|
|
|
if (!m_pXDGSurface || !m_pXDGSurface->owner /* happens at unmap */)
|
2023-03-03 12:17:43 +01:00
|
|
|
return -1;
|
|
|
|
|
2024-05-11 00:28:33 +02:00
|
|
|
wl_client_get_credentials(m_pXDGSurface->owner->client(), &PID, nullptr, nullptr);
|
2022-06-27 13:42:20 +02:00
|
|
|
} else {
|
2024-05-25 22:43:51 +02:00
|
|
|
if (!m_pXWaylandSurface)
|
2023-11-01 19:53:36 +01:00
|
|
|
return -1;
|
|
|
|
|
2024-05-25 22:43:51 +02:00
|
|
|
PID = m_pXWaylandSurface->pid;
|
2022-06-27 13:42:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return PID;
|
|
|
|
}
|
2022-07-16 12:44:45 +02:00
|
|
|
|
|
|
|
IHyprWindowDecoration* CWindow::getDecorationByType(eDecorationType type) {
|
|
|
|
for (auto& wd : m_dWindowDecorations) {
|
|
|
|
if (wd->getDecorationType() == type)
|
|
|
|
return wd.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
2022-08-06 20:57:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CWindow::updateToplevel() {
|
2024-01-09 18:14:08 +01:00
|
|
|
updateSurfaceScaleTransformDetails();
|
2022-08-08 21:20:41 +02:00
|
|
|
}
|
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
void CWindow::updateSurfaceScaleTransformDetails(bool force) {
|
2024-03-05 21:46:08 +01:00
|
|
|
if (!m_bIsMapped || m_bHidden || g_pCompositor->m_bUnsafeState)
|
2022-08-08 21:20:41 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(m_iLastSurfaceMonitorID);
|
|
|
|
|
|
|
|
m_iLastSurfaceMonitorID = m_iMonitorID;
|
|
|
|
|
|
|
|
const auto PNEWMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
|
|
|
|
2024-03-05 21:46:08 +01:00
|
|
|
if (!PNEWMONITOR)
|
|
|
|
return;
|
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
if (PNEWMONITOR != PLASTMONITOR || force) {
|
|
|
|
if (PLASTMONITOR && PLASTMONITOR->m_bEnabled && PNEWMONITOR != PLASTMONITOR)
|
|
|
|
m_pWLSurface->resource()->breadthfirst([PLASTMONITOR](SP<CWLSurfaceResource> s, const Vector2D& offset, void* d) { s->leave(PLASTMONITOR->self.lock()); }, nullptr);
|
2022-08-08 21:20:41 +02:00
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
m_pWLSurface->resource()->breadthfirst([PNEWMONITOR](SP<CWLSurfaceResource> s, const Vector2D& offset, void* d) { s->enter(PNEWMONITOR->self.lock()); }, nullptr);
|
2024-01-09 18:14:08 +01:00
|
|
|
}
|
2023-06-06 09:48:07 +02:00
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
m_pWLSurface->resource()->breadthfirst(
|
|
|
|
[this](SP<CWLSurfaceResource> s, const Vector2D& offset, void* d) {
|
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
2024-01-11 13:15:20 +01:00
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
const auto PSURFACE = CWLSurface::fromResource(s);
|
2024-01-11 13:15:20 +01:00
|
|
|
if (PSURFACE && PSURFACE->m_fLastScale == PMONITOR->scale)
|
|
|
|
return;
|
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
g_pCompositor->setPreferredScaleForSurface(s, PMONITOR->scale);
|
|
|
|
g_pCompositor->setPreferredTransformForSurface(s, PMONITOR->transform);
|
2023-06-06 09:48:07 +02:00
|
|
|
},
|
2024-06-08 10:07:59 +02:00
|
|
|
nullptr);
|
2022-08-21 17:01:26 +02:00
|
|
|
}
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
|
|
|
|
if (m_pWorkspace == pWorkspace)
|
2023-03-18 17:30:29 +01:00
|
|
|
return;
|
2022-08-21 17:01:26 +02:00
|
|
|
|
2024-04-24 17:16:46 +02:00
|
|
|
static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking");
|
|
|
|
|
2024-04-23 02:28:20 +02:00
|
|
|
if (!m_szInitialWorkspaceToken.empty()) {
|
2024-04-24 17:16:46 +02:00
|
|
|
const auto TOKEN = g_pTokenManager->getToken(m_szInitialWorkspaceToken);
|
|
|
|
if (TOKEN) {
|
|
|
|
if (*PINITIALWSTRACKING == 2) {
|
|
|
|
// persistent
|
|
|
|
SInitialWorkspaceToken token = std::any_cast<SInitialWorkspaceToken>(TOKEN->data);
|
2024-04-27 13:43:12 +02:00
|
|
|
if (token.primaryOwner.lock().get() == this) {
|
2024-04-24 17:16:46 +02:00
|
|
|
token.workspace = pWorkspace->getConfigName();
|
|
|
|
TOKEN->data = token;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-04-23 02:28:20 +02:00
|
|
|
}
|
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
static auto PCLOSEONLASTSPECIAL = CConfigValue<Hyprlang::INT>("misc:close_special_on_empty");
|
2023-10-24 01:58:44 +02:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto OLDWORKSPACE = m_pWorkspace;
|
2023-10-24 01:58:44 +02:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
m_pWorkspace = pWorkspace;
|
2023-03-18 17:30:29 +01:00
|
|
|
|
2024-03-19 03:52:52 +01:00
|
|
|
setAnimationsToMove();
|
|
|
|
|
2024-04-10 18:26:11 +02:00
|
|
|
g_pCompositor->updateWorkspaceWindows(OLDWORKSPACE->m_iID);
|
2024-07-11 16:10:42 +02:00
|
|
|
g_pCompositor->updateWorkspaceWindowData(OLDWORKSPACE->m_iID);
|
2024-04-19 19:46:16 +02:00
|
|
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(OLDWORKSPACE->m_iMonitorID);
|
|
|
|
|
2024-04-10 18:26:11 +02:00
|
|
|
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
2024-07-11 16:10:42 +02:00
|
|
|
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
2024-04-19 19:46:16 +02:00
|
|
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID);
|
|
|
|
|
2024-04-10 18:26:11 +02:00
|
|
|
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
2023-08-17 10:13:19 +02:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (valid(pWorkspace)) {
|
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"movewindow", std::format("{:x},{}", (uintptr_t)this, pWorkspace->m_szName)});
|
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"movewindowv2", std::format("{:x},{},{}", (uintptr_t)this, pWorkspace->m_iID, pWorkspace->m_szName)});
|
2024-04-27 13:43:12 +02:00
|
|
|
EMIT_HOOK_EVENT("moveWindow", (std::vector<std::any>{m_pSelf.lock(), pWorkspace}));
|
2022-08-21 17:01:26 +02:00
|
|
|
}
|
2023-03-18 17:30:29 +01:00
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
if (const auto SWALLOWED = m_pSwallowed.lock()) {
|
|
|
|
SWALLOWED->moveToWorkspace(pWorkspace);
|
|
|
|
SWALLOWED->m_iMonitorID = m_iMonitorID;
|
2023-04-02 11:24:17 +02:00
|
|
|
}
|
2023-08-15 19:15:37 +02:00
|
|
|
|
|
|
|
// update xwayland coords
|
2024-04-27 13:43:12 +02:00
|
|
|
g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.value());
|
2023-10-24 01:58:44 +02:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (OLDWORKSPACE && g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE->m_iID) && g_pCompositor->getWindowsOnWorkspace(OLDWORKSPACE->m_iID) == 0 && *PCLOSEONLASTSPECIAL) {
|
|
|
|
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(OLDWORKSPACE->m_iMonitorID); PMONITOR)
|
|
|
|
PMONITOR->setSpecialWorkspace(nullptr);
|
2023-10-24 01:58:44 +02:00
|
|
|
}
|
2022-08-28 19:47:06 +02:00
|
|
|
}
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
PHLWINDOW CWindow::X11TransientFor() {
|
2024-05-25 22:43:51 +02:00
|
|
|
if (!m_pXWaylandSurface || !m_pXWaylandSurface->parent)
|
2022-08-28 19:47:06 +02:00
|
|
|
return nullptr;
|
|
|
|
|
2024-07-01 00:26:08 +02:00
|
|
|
auto s = m_pXWaylandSurface->parent;
|
|
|
|
auto oldParent = s;
|
2024-05-25 22:43:51 +02:00
|
|
|
while (s) {
|
2024-07-01 00:26:08 +02:00
|
|
|
// break cyclic loop of m_pXWaylandSurface being parent of itself, #TODO reject this from even being created?
|
|
|
|
if (!s->parent || s->parent == oldParent)
|
2024-05-25 22:43:51 +02:00
|
|
|
break;
|
|
|
|
s = s->parent;
|
2022-08-28 19:47:06 +02:00
|
|
|
}
|
|
|
|
|
2024-05-25 22:43:51 +02:00
|
|
|
for (auto& w : g_pCompositor->m_vWindows) {
|
|
|
|
if (w->m_pXWaylandSurface != s)
|
|
|
|
continue;
|
|
|
|
return w;
|
|
|
|
}
|
2022-09-01 10:16:23 +02:00
|
|
|
|
2024-05-25 22:43:51 +02:00
|
|
|
return nullptr;
|
2022-08-28 19:47:06 +02:00
|
|
|
}
|
2022-08-29 19:52:35 +02:00
|
|
|
|
|
|
|
void CWindow::removeDecorationByType(eDecorationType type) {
|
|
|
|
for (auto& wd : m_dWindowDecorations) {
|
|
|
|
if (wd->getDecorationType() == type)
|
|
|
|
m_vDecosToRemove.push_back(wd.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
updateWindowDecos();
|
|
|
|
}
|
2022-10-14 21:46:32 +02:00
|
|
|
|
2022-11-04 16:56:31 +01:00
|
|
|
void unregisterVar(void* ptr) {
|
2024-03-02 01:35:17 +01:00
|
|
|
((CBaseAnimatedVariable*)ptr)->unregister();
|
2022-11-04 16:56:31 +01:00
|
|
|
}
|
|
|
|
|
2022-10-14 21:46:32 +02:00
|
|
|
void CWindow::onUnmap() {
|
2024-03-03 19:39:20 +01:00
|
|
|
static auto PCLOSEONLASTSPECIAL = CConfigValue<Hyprlang::INT>("misc:close_special_on_empty");
|
2023-09-03 13:00:02 +02:00
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
if (g_pCompositor->m_pLastWindow.lock().get() == this)
|
|
|
|
g_pCompositor->m_pLastWindow.reset();
|
|
|
|
if (g_pInputManager->currentlyDraggedWindow.lock().get() == this)
|
|
|
|
g_pInputManager->currentlyDraggedWindow.reset();
|
2022-11-04 16:56:31 +01:00
|
|
|
|
2024-04-24 17:16:46 +02:00
|
|
|
static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking");
|
|
|
|
|
|
|
|
if (!m_szInitialWorkspaceToken.empty()) {
|
|
|
|
const auto TOKEN = g_pTokenManager->getToken(m_szInitialWorkspaceToken);
|
|
|
|
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->data);
|
2024-04-27 13:43:12 +02:00
|
|
|
if (token.primaryOwner.lock().get() == this)
|
2024-04-24 17:16:46 +02:00
|
|
|
g_pTokenManager->removeToken(TOKEN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-04 23:49:15 +02:00
|
|
|
m_iLastWorkspace = m_pWorkspace->m_iID;
|
2024-04-02 21:32:39 +02:00
|
|
|
|
2022-11-04 16:56:31 +01:00
|
|
|
m_vRealPosition.setCallbackOnEnd(unregisterVar);
|
|
|
|
m_vRealSize.setCallbackOnEnd(unregisterVar);
|
2023-02-01 22:06:01 +01:00
|
|
|
m_fBorderFadeAnimationProgress.setCallbackOnEnd(unregisterVar);
|
|
|
|
m_fBorderAngleAnimationProgress.setCallbackOnEnd(unregisterVar);
|
2022-11-04 16:56:31 +01:00
|
|
|
m_fActiveInactiveAlpha.setCallbackOnEnd(unregisterVar);
|
|
|
|
m_fAlpha.setCallbackOnEnd(unregisterVar);
|
|
|
|
m_cRealShadowColor.setCallbackOnEnd(unregisterVar);
|
|
|
|
m_fDimPercent.setCallbackOnEnd(unregisterVar);
|
2022-11-06 18:52:09 +01:00
|
|
|
|
|
|
|
m_vRealSize.setCallbackOnBegin(nullptr);
|
2023-01-20 19:15:15 +01:00
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
std::erase_if(g_pCompositor->m_vWindowFocusHistory, [&](const auto& other) { return other.expired() || other.lock().get() == this; });
|
2023-03-23 01:39:32 +01:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (*PCLOSEONLASTSPECIAL && g_pCompositor->getWindowsOnWorkspace(workspaceID()) == 0 && onSpecialWorkspace()) {
|
2023-09-03 13:00:02 +02:00
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
2024-04-02 21:32:39 +02:00
|
|
|
if (PMONITOR && PMONITOR->activeSpecialWorkspace && PMONITOR->activeSpecialWorkspace == m_pWorkspace)
|
2023-09-03 13:00:02 +02:00
|
|
|
PMONITOR->setSpecialWorkspace(nullptr);
|
|
|
|
}
|
2023-09-28 22:48:33 +02:00
|
|
|
|
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID);
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
if (PMONITOR && PMONITOR->solitaryClient.lock().get() == this)
|
|
|
|
PMONITOR->solitaryClient.reset();
|
2023-12-20 23:52:18 +01:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
2024-07-11 16:10:42 +02:00
|
|
|
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
2024-04-19 19:46:16 +02:00
|
|
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID);
|
2024-04-10 18:26:11 +02:00
|
|
|
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
2024-02-29 01:03:28 +01:00
|
|
|
|
2024-04-12 20:52:01 +02:00
|
|
|
m_pWorkspace.reset();
|
|
|
|
|
2024-02-29 15:26:02 +01:00
|
|
|
if (m_bIsX11)
|
|
|
|
return;
|
|
|
|
|
2024-02-29 01:03:28 +01:00
|
|
|
m_pSubsurfaceHead.reset();
|
2024-02-29 15:26:02 +01:00
|
|
|
m_pPopupHead.reset();
|
2022-11-04 16:56:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CWindow::onMap() {
|
2022-11-18 14:53:54 +01:00
|
|
|
// 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_vRealPosition.resetAllCallbacks();
|
|
|
|
m_vRealSize.resetAllCallbacks();
|
2023-02-01 22:06:01 +01:00
|
|
|
m_fBorderFadeAnimationProgress.resetAllCallbacks();
|
|
|
|
m_fBorderAngleAnimationProgress.resetAllCallbacks();
|
2022-11-18 14:53:54 +01:00
|
|
|
m_fActiveInactiveAlpha.resetAllCallbacks();
|
|
|
|
m_fAlpha.resetAllCallbacks();
|
|
|
|
m_cRealShadowColor.resetAllCallbacks();
|
|
|
|
m_fDimPercent.resetAllCallbacks();
|
|
|
|
|
2022-11-04 16:56:31 +01:00
|
|
|
m_vRealPosition.registerVar();
|
|
|
|
m_vRealSize.registerVar();
|
2023-02-01 22:06:01 +01:00
|
|
|
m_fBorderFadeAnimationProgress.registerVar();
|
|
|
|
m_fBorderAngleAnimationProgress.registerVar();
|
2022-11-04 16:56:31 +01:00
|
|
|
m_fActiveInactiveAlpha.registerVar();
|
|
|
|
m_fAlpha.registerVar();
|
|
|
|
m_cRealShadowColor.registerVar();
|
|
|
|
m_fDimPercent.registerVar();
|
2022-11-06 18:52:09 +01:00
|
|
|
|
2023-02-01 22:06:01 +01:00
|
|
|
m_fBorderAngleAnimationProgress.setCallbackOnEnd([&](void* ptr) { onBorderAngleAnimEnd(ptr); }, false);
|
|
|
|
|
|
|
|
m_fBorderAngleAnimationProgress.setValueAndWarp(0.f);
|
|
|
|
m_fBorderAngleAnimationProgress = 1.f;
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
g_pCompositor->m_vWindowFocusHistory.push_back(m_pSelf);
|
2023-03-28 21:17:47 +02:00
|
|
|
|
2023-10-20 21:15:41 +02:00
|
|
|
m_vReportedSize = m_vPendingReportedSize;
|
2024-03-17 02:05:26 +01:00
|
|
|
m_bAnimatingIn = true;
|
2024-02-01 01:55:17 +01:00
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
updateSurfaceScaleTransformDetails(true);
|
|
|
|
|
2024-02-29 15:26:02 +01:00
|
|
|
if (m_bIsX11)
|
|
|
|
return;
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
m_pSubsurfaceHead = std::make_unique<CSubsurface>(m_pSelf.lock());
|
|
|
|
m_pPopupHead = std::make_unique<CPopup>(m_pSelf.lock());
|
2022-10-14 21:46:32 +02:00
|
|
|
}
|
|
|
|
|
2023-02-01 22:06:01 +01:00
|
|
|
void CWindow::onBorderAngleAnimEnd(void* ptr) {
|
2024-03-02 01:35:17 +01:00
|
|
|
const auto PANIMVAR = (CAnimatedVariable<float>*)ptr;
|
2023-02-01 22:06:01 +01:00
|
|
|
|
|
|
|
const std::string STYLE = PANIMVAR->getConfig()->pValues->internalStyle;
|
|
|
|
|
2023-02-14 18:10:17 +01:00
|
|
|
if (STYLE != "loop" || !PANIMVAR->getConfig()->pValues->internalEnabled)
|
2023-02-01 22:06:01 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
PANIMVAR->setCallbackOnEnd(nullptr); // we remove the callback here because otherwise setvalueandwarp will recurse this
|
|
|
|
|
|
|
|
PANIMVAR->setValueAndWarp(0);
|
|
|
|
*PANIMVAR = 1.f;
|
|
|
|
|
|
|
|
PANIMVAR->setCallbackOnEnd([&](void* ptr) { onBorderAngleAnimEnd(ptr); }, false);
|
|
|
|
}
|
|
|
|
|
2022-10-14 21:46:32 +02:00
|
|
|
void CWindow::setHidden(bool hidden) {
|
|
|
|
m_bHidden = hidden;
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
if (hidden && g_pCompositor->m_pLastWindow.lock().get() == this) {
|
|
|
|
g_pCompositor->m_pLastWindow.reset();
|
2022-10-14 21:46:32 +02:00
|
|
|
}
|
2023-12-23 22:30:49 +01:00
|
|
|
|
|
|
|
setSuspended(hidden);
|
2022-10-14 21:46:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CWindow::isHidden() {
|
|
|
|
return m_bHidden;
|
2022-11-15 11:21:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CWindow::applyDynamicRule(const SWindowRule& r) {
|
2024-07-11 16:10:42 +02:00
|
|
|
const eOverridePriority priority = r.szValue == "execRule" ? PRIORITY_SET_PROP : PRIORITY_WINDOW_RULE;
|
|
|
|
const CVarList VARS(r.szRule, 0, ' ');
|
|
|
|
if (r.szRule.starts_with("tag")) {
|
2024-05-28 23:37:24 +02:00
|
|
|
CVarList vars{r.szRule, 0, 's', true};
|
|
|
|
|
|
|
|
if (vars.size() == 2 && vars[0] == "tag")
|
|
|
|
m_tags.applyTag(vars[1], true);
|
|
|
|
else
|
|
|
|
Debug::log(ERR, "Tag rule invalid: {}", r.szRule);
|
2023-10-15 20:07:23 +02:00
|
|
|
} else if (r.szRule.starts_with("opacity")) {
|
2022-11-15 11:21:26 +01:00
|
|
|
try {
|
2022-12-11 18:15:02 +01:00
|
|
|
CVarList vars(r.szRule, 0, ' ');
|
|
|
|
|
2023-07-21 19:05:00 +02:00
|
|
|
int opacityIDX = 0;
|
|
|
|
|
|
|
|
for (auto& r : vars) {
|
|
|
|
if (r == "opacity")
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (r == "override") {
|
2024-04-09 17:22:44 +02:00
|
|
|
if (opacityIDX == 1)
|
2024-07-11 16:10:42 +02:00
|
|
|
m_sWindowData.alpha = CWindowOverridableVar(SAlphaValue{m_sWindowData.alpha.value().m_fAlpha, true}, priority);
|
2024-04-09 17:22:44 +02:00
|
|
|
else if (opacityIDX == 2)
|
2024-07-11 16:10:42 +02:00
|
|
|
m_sWindowData.alphaInactive = CWindowOverridableVar(SAlphaValue{m_sWindowData.alphaInactive.value().m_fAlpha, true}, priority);
|
2024-04-08 00:19:02 +02:00
|
|
|
else if (opacityIDX == 3)
|
2024-07-11 16:10:42 +02:00
|
|
|
m_sWindowData.alphaFullscreen = CWindowOverridableVar(SAlphaValue{m_sWindowData.alphaFullscreen.value().m_fAlpha, true}, priority);
|
2022-12-11 18:15:02 +01:00
|
|
|
} else {
|
2023-07-21 19:05:00 +02:00
|
|
|
if (opacityIDX == 0) {
|
2024-07-11 16:10:42 +02:00
|
|
|
m_sWindowData.alpha = CWindowOverridableVar(SAlphaValue{std::stof(r), false}, priority);
|
2023-07-21 19:05:00 +02:00
|
|
|
} else if (opacityIDX == 1) {
|
2024-07-11 16:10:42 +02:00
|
|
|
m_sWindowData.alphaInactive = CWindowOverridableVar(SAlphaValue{std::stof(r), false}, priority);
|
2024-04-08 00:19:02 +02:00
|
|
|
} else if (opacityIDX == 2) {
|
2024-07-11 16:10:42 +02:00
|
|
|
m_sWindowData.alphaFullscreen = CWindowOverridableVar(SAlphaValue{std::stof(r), false}, priority);
|
2022-12-11 18:15:02 +01:00
|
|
|
} else {
|
2024-04-08 00:19:02 +02:00
|
|
|
throw std::runtime_error("more than 3 alpha values");
|
2022-12-11 18:15:02 +01:00
|
|
|
}
|
2023-07-21 19:05:00 +02:00
|
|
|
|
|
|
|
opacityIDX++;
|
2022-12-11 18:15:02 +01:00
|
|
|
}
|
2022-11-15 11:21:26 +01:00
|
|
|
}
|
2024-04-09 17:22:44 +02:00
|
|
|
|
|
|
|
if (opacityIDX == 1) {
|
2024-07-11 16:10:42 +02:00
|
|
|
m_sWindowData.alphaInactive = m_sWindowData.alpha;
|
|
|
|
m_sWindowData.alphaFullscreen = m_sWindowData.alpha;
|
2024-04-09 17:22:44 +02:00
|
|
|
}
|
2023-09-06 21:45:37 +02:00
|
|
|
} catch (std::exception& e) { Debug::log(ERR, "Opacity rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
2023-10-15 20:07:23 +02:00
|
|
|
} else if (r.szRule.starts_with("animation")) {
|
2024-07-11 16:10:42 +02:00
|
|
|
auto STYLE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
|
|
|
m_sWindowData.animationStyle = CWindowOverridableVar(STYLE, priority);
|
2023-10-15 20:07:23 +02:00
|
|
|
} else if (r.szRule.starts_with("bordercolor")) {
|
2022-11-15 11:21:26 +01:00
|
|
|
try {
|
2024-01-14 18:27:32 +01:00
|
|
|
// Each vector will only get used if it has at least one color
|
|
|
|
CGradientValueData activeBorderGradient = {};
|
|
|
|
CGradientValueData inactiveBorderGradient = {};
|
|
|
|
bool active = true;
|
2024-06-11 17:17:45 +02:00
|
|
|
CVarList colorsAndAngles = CVarList(trim(r.szRule.substr(r.szRule.find_first_of(' ') + 1)), 0, 's', true);
|
2024-01-14 18:27:32 +01:00
|
|
|
|
|
|
|
// Basic form has only two colors, everything else can be parsed as a gradient
|
|
|
|
if (colorsAndAngles.size() == 2 && !colorsAndAngles[1].contains("deg")) {
|
2024-07-11 16:10:42 +02:00
|
|
|
m_sWindowData.activeBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[0]))), priority);
|
|
|
|
m_sWindowData.inactiveBorderColor = CWindowOverridableVar(CGradientValueData(CColor(configStringToInt(colorsAndAngles[1]))), priority);
|
2024-01-14 18:27:32 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto& token : colorsAndAngles) {
|
|
|
|
// The first angle, or an explicit "0deg", splits the two gradients
|
|
|
|
if (active && token.contains("deg")) {
|
|
|
|
activeBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
|
|
|
|
active = false;
|
|
|
|
} else if (token.contains("deg"))
|
|
|
|
inactiveBorderGradient.m_fAngle = std::stoi(token.substr(0, token.size() - 3)) * (PI / 180.0);
|
|
|
|
else if (active)
|
|
|
|
activeBorderGradient.m_vColors.push_back(configStringToInt(token));
|
|
|
|
else
|
|
|
|
inactiveBorderGradient.m_vColors.push_back(configStringToInt(token));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Includes sanity checks for the number of colors in each gradient
|
|
|
|
if (activeBorderGradient.m_vColors.size() > 10 || inactiveBorderGradient.m_vColors.size() > 10)
|
|
|
|
Debug::log(WARN, "Bordercolor rule \"{}\" has more than 10 colors in one gradient, ignoring", r.szRule);
|
|
|
|
else if (activeBorderGradient.m_vColors.empty())
|
|
|
|
Debug::log(WARN, "Bordercolor rule \"{}\" has no colors, ignoring", r.szRule);
|
|
|
|
else if (inactiveBorderGradient.m_vColors.empty())
|
2024-07-11 16:10:42 +02:00
|
|
|
m_sWindowData.activeBorderColor = CWindowOverridableVar(activeBorderGradient, priority);
|
2024-01-14 18:27:32 +01:00
|
|
|
else {
|
2024-07-11 16:10:42 +02:00
|
|
|
m_sWindowData.activeBorderColor = CWindowOverridableVar(activeBorderGradient, priority);
|
|
|
|
m_sWindowData.inactiveBorderColor = CWindowOverridableVar(inactiveBorderGradient, priority);
|
2022-11-15 11:21:26 +01:00
|
|
|
}
|
2023-09-06 21:45:37 +02:00
|
|
|
} catch (std::exception& e) { Debug::log(ERR, "BorderColor rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
2024-07-11 16:10:42 +02:00
|
|
|
} else if (auto search = g_pConfigManager->mbWindowProperties.find(VARS[0]); search != g_pConfigManager->mbWindowProperties.end()) {
|
|
|
|
if (VARS[1].empty()) {
|
|
|
|
*(search->second(m_pSelf.lock())) = CWindowOverridableVar(true, priority);
|
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
*(search->second(m_pSelf.lock())) = CWindowOverridableVar((bool)configStringToInt(VARS[1]), priority);
|
|
|
|
} catch (...) {}
|
|
|
|
}
|
|
|
|
} else if (auto search = g_pConfigManager->miWindowProperties.find(VARS[0]); search != g_pConfigManager->miWindowProperties.end()) {
|
2023-08-09 22:03:24 +02:00
|
|
|
try {
|
2024-07-11 16:10:42 +02:00
|
|
|
*(search->second(m_pSelf.lock())) = CWindowOverridableVar(std::stoi(VARS[1]), priority);
|
|
|
|
} catch (std::exception& e) { Debug::log(ERR, "Rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
2023-11-14 16:46:57 +01:00
|
|
|
} else if (r.szRule.starts_with("idleinhibit")) {
|
|
|
|
auto IDLERULE = r.szRule.substr(r.szRule.find_first_of(' ') + 1);
|
|
|
|
|
|
|
|
if (IDLERULE == "none")
|
|
|
|
m_eIdleInhibitMode = IDLEINHIBIT_NONE;
|
|
|
|
else if (IDLERULE == "always")
|
|
|
|
m_eIdleInhibitMode = IDLEINHIBIT_ALWAYS;
|
|
|
|
else if (IDLERULE == "focus")
|
|
|
|
m_eIdleInhibitMode = IDLEINHIBIT_FOCUS;
|
|
|
|
else if (IDLERULE == "fullscreen")
|
|
|
|
m_eIdleInhibitMode = IDLEINHIBIT_FULLSCREEN;
|
|
|
|
else
|
|
|
|
Debug::log(ERR, "Rule idleinhibit: unknown mode {}", IDLERULE);
|
2024-03-08 03:24:44 +01:00
|
|
|
} else if (r.szRule.starts_with("maxsize")) {
|
|
|
|
try {
|
2024-03-08 15:54:45 +01:00
|
|
|
if (!m_bIsFloating)
|
|
|
|
return;
|
2024-03-08 18:10:38 +01:00
|
|
|
const auto VEC = configStringToVector2D(r.szRule.substr(8));
|
|
|
|
if (VEC.x < 1 || VEC.y < 1) {
|
|
|
|
Debug::log(ERR, "Invalid size for maxsize");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-07-11 16:10:42 +02:00
|
|
|
m_sWindowData.maxSize = CWindowOverridableVar(VEC, priority);
|
|
|
|
m_vRealSize =
|
|
|
|
Vector2D(std::min((double)m_sWindowData.maxSize.value().x, m_vRealSize.goal().x), std::min((double)m_sWindowData.maxSize.value().y, m_vRealSize.goal().y));
|
2024-04-27 13:43:12 +02:00
|
|
|
g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal());
|
2024-03-08 03:24:44 +01:00
|
|
|
} catch (std::exception& e) { Debug::log(ERR, "maxsize rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
|
|
|
} else if (r.szRule.starts_with("minsize")) {
|
|
|
|
try {
|
2024-03-08 15:54:45 +01:00
|
|
|
if (!m_bIsFloating)
|
|
|
|
return;
|
2024-03-08 18:10:38 +01:00
|
|
|
const auto VEC = configStringToVector2D(r.szRule.substr(8));
|
|
|
|
if (VEC.x < 1 || VEC.y < 1) {
|
|
|
|
Debug::log(ERR, "Invalid size for minsize");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-07-11 16:10:42 +02:00
|
|
|
m_sWindowData.minSize = CWindowOverridableVar(VEC, priority);
|
|
|
|
m_vRealSize =
|
|
|
|
Vector2D(std::max((double)m_sWindowData.minSize.value().x, m_vRealSize.goal().x), std::max((double)m_sWindowData.minSize.value().y, m_vRealSize.goal().y));
|
2024-04-27 13:43:12 +02:00
|
|
|
g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal());
|
2024-05-03 03:00:58 +02:00
|
|
|
if (m_sGroupData.pNextWindow.expired())
|
|
|
|
setHidden(false);
|
2024-03-08 03:24:44 +01:00
|
|
|
} catch (std::exception& e) { Debug::log(ERR, "minsize rule \"{}\" failed with: {}", r.szRule, e.what()); }
|
2022-11-15 11:21:26 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CWindow::updateDynamicRules() {
|
2024-07-11 16:10:42 +02:00
|
|
|
m_sWindowData.alpha.unset(PRIORITY_WINDOW_RULE);
|
|
|
|
m_sWindowData.alphaInactive.unset(PRIORITY_WINDOW_RULE);
|
|
|
|
m_sWindowData.alphaFullscreen.unset(PRIORITY_WINDOW_RULE);
|
|
|
|
|
|
|
|
unsetWindowData(PRIORITY_WINDOW_RULE);
|
|
|
|
|
|
|
|
m_sWindowData.animationStyle.unset(PRIORITY_WINDOW_RULE);
|
|
|
|
m_sWindowData.maxSize.unset(PRIORITY_WINDOW_RULE);
|
|
|
|
m_sWindowData.minSize.unset(PRIORITY_WINDOW_RULE);
|
|
|
|
|
|
|
|
m_sWindowData.activeBorderColor.unset(PRIORITY_WINDOW_RULE);
|
|
|
|
m_sWindowData.inactiveBorderColor.unset(PRIORITY_WINDOW_RULE);
|
|
|
|
|
|
|
|
m_eIdleInhibitMode = IDLEINHIBIT_NONE;
|
2022-11-15 11:21:26 +01:00
|
|
|
|
2024-05-28 23:37:24 +02:00
|
|
|
m_tags.removeDynamicTags();
|
|
|
|
|
2024-05-02 03:17:55 +02:00
|
|
|
m_vMatchedRules = g_pConfigManager->getMatchingRules(m_pSelf.lock());
|
|
|
|
for (auto& r : m_vMatchedRules) {
|
2022-11-15 11:21:26 +01:00
|
|
|
applyDynamicRule(r);
|
|
|
|
}
|
2023-07-18 00:11:43 +02:00
|
|
|
|
2024-05-02 03:17:55 +02:00
|
|
|
EMIT_HOOK_EVENT("windowUpdateRules", m_pSelf.lock());
|
|
|
|
|
2023-07-18 11:49:57 +02:00
|
|
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID);
|
2022-11-15 11:21:26 +01:00
|
|
|
}
|
2023-02-18 23:35:31 +01:00
|
|
|
|
|
|
|
// 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) {
|
2023-08-17 10:13:19 +02:00
|
|
|
const int ROUNDING = rounding();
|
|
|
|
if (getRealBorderSize() >= ROUNDING)
|
2023-02-18 23:35:31 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// (x0, y0), (x0, y1), ... are the center point of rounding at each corner
|
2024-03-02 01:35:17 +01:00
|
|
|
double x0 = m_vRealPosition.value().x + ROUNDING;
|
|
|
|
double y0 = m_vRealPosition.value().y + ROUNDING;
|
|
|
|
double x1 = m_vRealPosition.value().x + m_vRealSize.value().x - ROUNDING;
|
|
|
|
double y1 = m_vRealPosition.value().y + m_vRealSize.value().y - ROUNDING;
|
2023-02-18 23:35:31 +01:00
|
|
|
|
|
|
|
if (x < x0 && y < y0) {
|
2023-08-17 10:13:19 +02:00
|
|
|
return Vector2D{x0, y0}.distance(Vector2D{x, y}) > (double)ROUNDING;
|
2023-02-18 23:35:31 +01:00
|
|
|
}
|
|
|
|
if (x > x1 && y < y0) {
|
2023-08-17 10:13:19 +02:00
|
|
|
return Vector2D{x1, y0}.distance(Vector2D{x, y}) > (double)ROUNDING;
|
2023-02-18 23:35:31 +01:00
|
|
|
}
|
|
|
|
if (x < x0 && y > y1) {
|
2023-08-17 10:13:19 +02:00
|
|
|
return Vector2D{x0, y1}.distance(Vector2D{x, y}) > (double)ROUNDING;
|
2023-02-18 23:35:31 +01:00
|
|
|
}
|
|
|
|
if (x > x1 && y > y1) {
|
2023-08-17 10:13:19 +02:00
|
|
|
return Vector2D{x1, y1}.distance(Vector2D{x, y}) > (double)ROUNDING;
|
2023-02-18 23:35:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// checks if the wayland window has a popup at pos
|
|
|
|
bool CWindow::hasPopupAt(const Vector2D& pos) {
|
|
|
|
if (m_bIsX11)
|
|
|
|
return false;
|
|
|
|
|
2024-05-11 00:28:33 +02:00
|
|
|
CPopup* popup = m_pPopupHead->at(pos);
|
2023-02-18 23:35:31 +01:00
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
return popup && popup->m_pWLSurface->resource();
|
2023-02-18 23:35:31 +01:00
|
|
|
}
|
2023-02-19 22:07:32 +01:00
|
|
|
|
2023-09-22 01:42:00 +02:00
|
|
|
void CWindow::applyGroupRules() {
|
|
|
|
if ((m_eGroupRules & GROUP_SET && m_bFirstMap) || m_eGroupRules & GROUP_SET_ALWAYS)
|
|
|
|
createGroup();
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
if (m_sGroupData.pNextWindow.lock() && ((m_eGroupRules & GROUP_LOCK && m_bFirstMap) || m_eGroupRules & GROUP_LOCK_ALWAYS))
|
2023-09-22 01:42:00 +02:00
|
|
|
getGroupHead()->m_sGroupData.locked = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CWindow::createGroup() {
|
|
|
|
if (m_sGroupData.deny) {
|
|
|
|
Debug::log(LOG, "createGroup: window:{:x},title:{} is denied as a group, ignored", (uintptr_t)this, this->m_szTitle);
|
|
|
|
return;
|
|
|
|
}
|
2023-11-11 15:37:17 +01:00
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
if (m_sGroupData.pNextWindow.expired()) {
|
|
|
|
m_sGroupData.pNextWindow = m_pSelf;
|
2023-09-22 01:42:00 +02:00
|
|
|
m_sGroupData.head = true;
|
|
|
|
m_sGroupData.locked = false;
|
|
|
|
m_sGroupData.deny = false;
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(m_pSelf.lock()));
|
2023-09-22 01:42:00 +02:00
|
|
|
|
2024-04-10 18:26:11 +02:00
|
|
|
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
2024-07-11 16:10:42 +02:00
|
|
|
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
2024-04-19 19:46:16 +02:00
|
|
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID);
|
2023-09-22 01:42:00 +02:00
|
|
|
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
2024-05-07 13:00:55 +02:00
|
|
|
|
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"togglegroup", std::format("1,{:x}", (uintptr_t)this)});
|
2023-09-22 01:42:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CWindow::destroyGroup() {
|
2024-04-27 13:43:12 +02:00
|
|
|
if (m_sGroupData.pNextWindow.lock().get() == this) {
|
2023-09-22 01:42:00 +02:00
|
|
|
if (m_eGroupRules & GROUP_SET_ALWAYS) {
|
|
|
|
Debug::log(LOG, "destoryGroup: window:{:x},title:{} has rule [group set always], ignored", (uintptr_t)this, this->m_szTitle);
|
|
|
|
return;
|
|
|
|
}
|
2024-04-27 13:43:12 +02:00
|
|
|
m_sGroupData.pNextWindow.reset();
|
|
|
|
m_sGroupData.head = false;
|
2023-09-22 01:42:00 +02:00
|
|
|
updateWindowDecos();
|
2024-04-10 18:26:11 +02:00
|
|
|
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
2024-07-11 16:10:42 +02:00
|
|
|
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
2024-04-19 19:46:16 +02:00
|
|
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID);
|
2024-04-10 18:26:11 +02:00
|
|
|
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
2024-05-07 13:00:55 +02:00
|
|
|
|
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"togglegroup", std::format("0,{:x}", (uintptr_t)this)});
|
2023-09-22 01:42:00 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-05-07 13:00:55 +02:00
|
|
|
std::string addresses;
|
2024-04-27 13:43:12 +02:00
|
|
|
PHLWINDOW curr = m_pSelf.lock();
|
|
|
|
std::vector<PHLWINDOW> members;
|
2023-09-22 01:42:00 +02:00
|
|
|
do {
|
2024-04-27 13:43:12 +02:00
|
|
|
const auto PLASTWIN = curr;
|
|
|
|
curr = curr->m_sGroupData.pNextWindow.lock();
|
|
|
|
PLASTWIN->m_sGroupData.pNextWindow.reset();
|
2023-09-22 01:42:00 +02:00
|
|
|
curr->setHidden(false);
|
|
|
|
members.push_back(curr);
|
2024-05-07 13:00:55 +02:00
|
|
|
|
|
|
|
addresses += std::format("{:x},", (uintptr_t)curr.get());
|
2024-04-27 13:43:12 +02:00
|
|
|
} while (curr.get() != this);
|
2023-09-22 01:42:00 +02:00
|
|
|
|
|
|
|
for (auto& w : members) {
|
|
|
|
if (w->m_sGroupData.head)
|
|
|
|
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(curr);
|
|
|
|
w->m_sGroupData.head = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_bGroupsLocked;
|
|
|
|
g_pKeybindManager->m_bGroupsLocked = true;
|
|
|
|
for (auto& w : members) {
|
|
|
|
g_pLayoutManager->getCurrentLayout()->onWindowCreated(w);
|
|
|
|
w->updateWindowDecos();
|
|
|
|
}
|
|
|
|
g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV;
|
2024-04-10 18:26:11 +02:00
|
|
|
|
|
|
|
g_pCompositor->updateWorkspaceWindows(workspaceID());
|
2024-07-11 16:10:42 +02:00
|
|
|
g_pCompositor->updateWorkspaceWindowData(workspaceID());
|
2024-04-19 19:46:16 +02:00
|
|
|
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m_iMonitorID);
|
2024-04-10 18:26:11 +02:00
|
|
|
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
2024-05-07 13:00:55 +02:00
|
|
|
|
|
|
|
if (!addresses.empty())
|
|
|
|
addresses.pop_back();
|
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"togglegroup", std::format("0,{}", addresses)});
|
2023-09-22 01:42:00 +02:00
|
|
|
}
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
PHLWINDOW CWindow::getGroupHead() {
|
|
|
|
PHLWINDOW curr = m_pSelf.lock();
|
2023-02-19 22:07:32 +01:00
|
|
|
while (!curr->m_sGroupData.head)
|
2024-04-27 13:43:12 +02:00
|
|
|
curr = curr->m_sGroupData.pNextWindow.lock();
|
2023-02-19 22:07:32 +01:00
|
|
|
return curr;
|
|
|
|
}
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
PHLWINDOW CWindow::getGroupTail() {
|
|
|
|
PHLWINDOW curr = m_pSelf.lock();
|
2024-05-05 18:16:00 +02:00
|
|
|
while (!curr->m_sGroupData.pNextWindow->m_sGroupData.head)
|
2024-04-27 13:43:12 +02:00
|
|
|
curr = curr->m_sGroupData.pNextWindow.lock();
|
2023-02-19 22:07:32 +01:00
|
|
|
return curr;
|
|
|
|
}
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
PHLWINDOW CWindow::getGroupCurrent() {
|
|
|
|
PHLWINDOW curr = m_pSelf.lock();
|
2023-02-19 22:07:32 +01:00
|
|
|
while (curr->isHidden())
|
2024-04-27 13:43:12 +02:00
|
|
|
curr = curr->m_sGroupData.pNextWindow.lock();
|
2023-02-19 22:07:32 +01:00
|
|
|
return curr;
|
|
|
|
}
|
|
|
|
|
2023-08-30 17:39:22 +02:00
|
|
|
int CWindow::getGroupSize() {
|
2024-04-27 13:43:12 +02:00
|
|
|
int size = 1;
|
|
|
|
PHLWINDOW curr = m_pSelf.lock();
|
|
|
|
while (curr->m_sGroupData.pNextWindow.lock().get() != this) {
|
|
|
|
curr = curr->m_sGroupData.pNextWindow.lock();
|
2023-08-30 17:39:22 +02:00
|
|
|
size++;
|
|
|
|
}
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
bool CWindow::canBeGroupedInto(PHLWINDOW pWindow) {
|
|
|
|
return !g_pKeybindManager->m_bGroupsLocked // global group lock disengaged
|
|
|
|
&& ((m_eGroupRules & GROUP_INVADE && m_bFirstMap) // window ignore local group locks, or
|
|
|
|
|| (!pWindow->getGroupHead()->m_sGroupData.locked // target unlocked
|
|
|
|
&& !(m_sGroupData.pNextWindow.lock() && getGroupHead()->m_sGroupData.locked))) // source unlocked or isn't group
|
|
|
|
&& !m_sGroupData.deny // source is not denied entry
|
|
|
|
&& !(m_eGroupRules & GROUP_BARRED && m_bFirstMap); // group rule doesn't prevent adding window
|
2023-10-30 15:54:12 +01:00
|
|
|
}
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
PHLWINDOW CWindow::getGroupWindowByIndex(int index) {
|
2023-08-30 17:39:22 +02:00
|
|
|
const int SIZE = getGroupSize();
|
|
|
|
index = ((index % SIZE) + SIZE) % SIZE;
|
2024-04-27 13:43:12 +02:00
|
|
|
PHLWINDOW curr = getGroupHead();
|
2023-08-30 17:39:22 +02:00
|
|
|
while (index > 0) {
|
2024-04-27 13:43:12 +02:00
|
|
|
curr = curr->m_sGroupData.pNextWindow.lock();
|
2023-08-30 17:39:22 +02:00
|
|
|
index--;
|
|
|
|
}
|
|
|
|
return curr;
|
|
|
|
}
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
void CWindow::setGroupCurrent(PHLWINDOW pWindow) {
|
|
|
|
PHLWINDOW curr = m_sGroupData.pNextWindow.lock();
|
|
|
|
bool isMember = false;
|
|
|
|
while (curr.get() != this) {
|
2023-02-19 22:07:32 +01:00
|
|
|
if (curr == pWindow) {
|
|
|
|
isMember = true;
|
|
|
|
break;
|
|
|
|
}
|
2024-04-27 13:43:12 +02:00
|
|
|
curr = curr->m_sGroupData.pNextWindow.lock();
|
2023-02-19 22:07:32 +01:00
|
|
|
}
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
if (!isMember && pWindow.get() != this)
|
2023-02-19 22:07:32 +01:00
|
|
|
return;
|
|
|
|
|
2023-03-10 16:19:02 +01:00
|
|
|
const auto PCURRENT = getGroupCurrent();
|
|
|
|
const bool FULLSCREEN = PCURRENT->m_bIsFullscreen;
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto WORKSPACE = PCURRENT->m_pWorkspace;
|
2023-02-19 22:07:32 +01:00
|
|
|
|
2024-03-02 01:35:17 +01:00
|
|
|
const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goal();
|
|
|
|
const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goal();
|
2023-02-19 22:07:32 +01:00
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
const auto CURRENTISFOCUS = PCURRENT == g_pCompositor->m_pLastWindow.lock();
|
2023-02-19 22:07:32 +01:00
|
|
|
|
2023-03-10 16:19:02 +01:00
|
|
|
if (FULLSCREEN)
|
|
|
|
g_pCompositor->setWindowFullscreen(PCURRENT, false, WORKSPACE->m_efFullscreenMode);
|
|
|
|
|
2023-02-19 22:07:32 +01:00
|
|
|
PCURRENT->setHidden(true);
|
2023-08-15 19:15:37 +02:00
|
|
|
pWindow->setHidden(false); // can remove m_pLastWindow
|
2023-02-19 22:07:32 +01:00
|
|
|
|
|
|
|
g_pLayoutManager->getCurrentLayout()->replaceWindowDataWith(PCURRENT, pWindow);
|
|
|
|
|
|
|
|
if (PCURRENT->m_bIsFloating) {
|
|
|
|
pWindow->m_vRealPosition.setValueAndWarp(PWINDOWPOS);
|
|
|
|
pWindow->m_vRealSize.setValueAndWarp(PWINDOWSIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
|
|
|
|
|
|
|
if (CURRENTISFOCUS)
|
|
|
|
g_pCompositor->focusWindow(pWindow);
|
2023-03-10 16:19:02 +01:00
|
|
|
|
|
|
|
if (FULLSCREEN)
|
|
|
|
g_pCompositor->setWindowFullscreen(pWindow, true, WORKSPACE->m_efFullscreenMode);
|
2023-06-14 19:44:51 +02:00
|
|
|
|
|
|
|
g_pHyprRenderer->damageWindow(pWindow);
|
2023-11-11 15:37:17 +01:00
|
|
|
|
|
|
|
pWindow->updateWindowDecos();
|
2023-02-19 22:07:32 +01:00
|
|
|
}
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
void CWindow::insertWindowToGroup(PHLWINDOW pWindow) {
|
|
|
|
const auto BEGINAT = m_pSelf.lock();
|
|
|
|
const auto ENDAT = m_sGroupData.pNextWindow.lock();
|
2023-02-19 23:19:40 +01:00
|
|
|
|
2023-09-10 23:59:10 +02:00
|
|
|
if (!pWindow->getDecorationByType(DECORATION_GROUPBAR))
|
2023-11-11 15:37:17 +01:00
|
|
|
pWindow->addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
2023-09-10 23:59:10 +02:00
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
if (!pWindow->m_sGroupData.pNextWindow.lock()) {
|
2023-07-20 19:48:32 +02:00
|
|
|
BEGINAT->m_sGroupData.pNextWindow = pWindow;
|
|
|
|
pWindow->m_sGroupData.pNextWindow = ENDAT;
|
|
|
|
pWindow->m_sGroupData.head = false;
|
2023-02-19 23:19:40 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-07-20 19:48:32 +02:00
|
|
|
const auto SHEAD = pWindow->getGroupHead();
|
|
|
|
const auto STAIL = pWindow->getGroupTail();
|
|
|
|
|
|
|
|
SHEAD->m_sGroupData.head = false;
|
|
|
|
BEGINAT->m_sGroupData.pNextWindow = SHEAD;
|
|
|
|
STAIL->m_sGroupData.pNextWindow = ENDAT;
|
2023-03-18 17:30:29 +01:00
|
|
|
}
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
PHLWINDOW CWindow::getGroupPrevious() {
|
|
|
|
PHLWINDOW curr = m_sGroupData.pNextWindow.lock();
|
2023-07-13 17:55:20 +02:00
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
while (curr != m_pSelf.lock() && curr->m_sGroupData.pNextWindow.lock().get() != this)
|
|
|
|
curr = curr->m_sGroupData.pNextWindow.lock();
|
2023-07-13 17:55:20 +02:00
|
|
|
|
|
|
|
return curr;
|
|
|
|
}
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
void CWindow::switchWithWindowInGroup(PHLWINDOW pWindow) {
|
|
|
|
if (!m_sGroupData.pNextWindow.lock() || !pWindow->m_sGroupData.pNextWindow.lock())
|
2023-07-13 17:55:20 +02:00
|
|
|
return;
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
if (m_sGroupData.pNextWindow.lock() == pWindow) { // A -> this -> pWindow -> B >> A -> pWindow -> this -> B
|
2023-07-20 19:48:32 +02:00
|
|
|
getGroupPrevious()->m_sGroupData.pNextWindow = pWindow;
|
|
|
|
m_sGroupData.pNextWindow = pWindow->m_sGroupData.pNextWindow;
|
2024-04-27 13:43:12 +02:00
|
|
|
pWindow->m_sGroupData.pNextWindow = m_pSelf;
|
2023-07-13 17:55:20 +02:00
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
} else if (pWindow->m_sGroupData.pNextWindow.lock().get() == this) { // A -> pWindow -> this -> B >> A -> this -> pWindow -> B
|
|
|
|
pWindow->getGroupPrevious()->m_sGroupData.pNextWindow = m_pSelf;
|
2023-07-20 19:48:32 +02:00
|
|
|
pWindow->m_sGroupData.pNextWindow = m_sGroupData.pNextWindow;
|
|
|
|
m_sGroupData.pNextWindow = pWindow;
|
2023-07-13 17:55:20 +02:00
|
|
|
|
2023-07-20 19:48:32 +02:00
|
|
|
} else { // A -> this -> B | C -> pWindow -> D >> A -> pWindow -> B | C -> this -> D
|
|
|
|
std::swap(m_sGroupData.pNextWindow, pWindow->m_sGroupData.pNextWindow);
|
|
|
|
std::swap(getGroupPrevious()->m_sGroupData.pNextWindow, pWindow->getGroupPrevious()->m_sGroupData.pNextWindow);
|
2023-07-13 17:55:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
std::swap(m_sGroupData.head, pWindow->m_sGroupData.head);
|
2023-07-20 19:48:32 +02:00
|
|
|
std::swap(m_sGroupData.locked, pWindow->m_sGroupData.locked);
|
2023-07-13 17:55:20 +02:00
|
|
|
}
|
|
|
|
|
2023-03-18 17:30:29 +01:00
|
|
|
void CWindow::updateGroupOutputs() {
|
2024-04-27 13:43:12 +02:00
|
|
|
if (m_sGroupData.pNextWindow.expired())
|
2023-03-18 17:30:29 +01:00
|
|
|
return;
|
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
PHLWINDOW curr = m_sGroupData.pNextWindow.lock();
|
2024-04-02 21:32:39 +02:00
|
|
|
|
|
|
|
const auto WS = m_pWorkspace;
|
2023-03-18 17:30:29 +01:00
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
while (curr.get() != this) {
|
2023-03-18 17:30:29 +01:00
|
|
|
curr->m_iMonitorID = m_iMonitorID;
|
2024-04-02 21:32:39 +02:00
|
|
|
curr->moveToWorkspace(WS);
|
2023-03-18 17:30:29 +01:00
|
|
|
|
2024-03-02 01:35:17 +01:00
|
|
|
curr->m_vRealPosition = m_vRealPosition.goal();
|
|
|
|
curr->m_vRealSize = m_vRealSize.goal();
|
2023-03-18 17:30:29 +01:00
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
curr = curr->m_sGroupData.pNextWindow.lock();
|
2023-03-18 17:30:29 +01:00
|
|
|
}
|
2023-04-14 16:03:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Vector2D CWindow::middle() {
|
2024-03-02 01:35:17 +01:00
|
|
|
return m_vRealPosition.goal() + m_vRealSize.goal() / 2.f;
|
2023-04-14 16:03:53 +02:00
|
|
|
}
|
2023-04-22 13:36:50 +02:00
|
|
|
|
|
|
|
bool CWindow::opaque() {
|
2024-03-02 01:35:17 +01:00
|
|
|
if (m_fAlpha.value() != 1.f || m_fActiveInactiveAlpha.value() != 1.f)
|
2023-07-19 16:13:55 +02:00
|
|
|
return false;
|
|
|
|
|
2024-03-17 17:08:54 +01:00
|
|
|
if (m_vRealSize.goal().floor() != m_vReportedSize)
|
|
|
|
return false;
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PWORKSPACE = m_pWorkspace;
|
2023-07-19 16:13:55 +02:00
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
if (m_pWLSurface->small() && !m_pWLSurface->m_bFillIgnoreSmall)
|
2023-10-20 21:15:41 +02:00
|
|
|
return false;
|
|
|
|
|
2024-03-02 01:35:17 +01:00
|
|
|
if (PWORKSPACE->m_fAlpha.value() != 1.f)
|
2023-07-19 16:13:55 +02:00
|
|
|
return false;
|
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
if (m_bIsX11 && m_pXWaylandSurface && m_pXWaylandSurface->surface && m_pXWaylandSurface->surface->current.buffer)
|
|
|
|
return m_pXWaylandSurface->surface->current.buffer->opaque;
|
2023-04-22 13:36:50 +02:00
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
if (!m_pWLSurface->resource() || !m_pWLSurface->resource()->current.buffer)
|
|
|
|
return false;
|
2023-04-22 13:36:50 +02:00
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
// TODO: this is wrong
|
|
|
|
const auto EXTENTS = m_pXDGSurface->surface->current.opaque.getExtents();
|
|
|
|
if (EXTENTS.w >= m_pXDGSurface->surface->current.buffer->size.x && EXTENTS.h >= m_pXDGSurface->surface->current.buffer->size.y)
|
2023-04-22 13:36:50 +02:00
|
|
|
return true;
|
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
return m_pWLSurface->resource()->current.buffer->opaque;
|
2023-04-22 13:36:50 +02:00
|
|
|
}
|
2023-07-19 16:13:55 +02:00
|
|
|
|
|
|
|
float CWindow::rounding() {
|
2024-03-03 19:39:20 +01:00
|
|
|
static auto PROUNDING = CConfigValue<Hyprlang::INT>("decoration:rounding");
|
2023-07-19 16:13:55 +02:00
|
|
|
|
2024-07-11 16:10:42 +02:00
|
|
|
float rounding = m_sWindowData.rounding.valueOr(*PROUNDING);
|
2023-07-19 16:13:55 +02:00
|
|
|
|
2024-07-11 16:10:42 +02:00
|
|
|
return m_sWindowData.noRounding.valueOrDefault() ? 0 : rounding;
|
2023-07-19 16:13:55 +02:00
|
|
|
}
|
2023-08-17 10:13:19 +02:00
|
|
|
|
2024-07-11 16:10:42 +02:00
|
|
|
void CWindow::updateWindowData() {
|
2024-04-10 18:26:11 +02:00
|
|
|
const auto PWORKSPACE = m_pWorkspace;
|
|
|
|
const auto WORKSPACERULE = PWORKSPACE ? g_pConfigManager->getWorkspaceRuleFor(PWORKSPACE) : SWorkspaceRule{};
|
2024-07-11 16:10:42 +02:00
|
|
|
updateWindowData(WORKSPACERULE);
|
2024-04-10 18:26:11 +02:00
|
|
|
}
|
2023-08-17 10:13:19 +02:00
|
|
|
|
2024-07-11 16:10:42 +02:00
|
|
|
void CWindow::updateWindowData(const SWorkspaceRule& workspaceRule) {
|
2024-03-03 19:39:20 +01:00
|
|
|
static auto PNOBORDERONFLOATING = CConfigValue<Hyprlang::INT>("general:no_border_on_floating");
|
2024-02-18 16:00:34 +01:00
|
|
|
|
2024-07-11 16:10:42 +02:00
|
|
|
if (*PNOBORDERONFLOATING)
|
|
|
|
m_sWindowData.noBorder = CWindowOverridableVar(m_bIsFloating, PRIORITY_LAYOUT);
|
|
|
|
else
|
|
|
|
m_sWindowData.noBorder.unset(PRIORITY_LAYOUT);
|
2023-08-17 10:13:19 +02:00
|
|
|
|
2024-07-11 16:10:42 +02:00
|
|
|
m_sWindowData.borderSize.matchOptional(workspaceRule.borderSize, PRIORITY_WORKSPACE_RULE);
|
|
|
|
m_sWindowData.decorate.matchOptional(workspaceRule.decorate, PRIORITY_WORKSPACE_RULE);
|
|
|
|
m_sWindowData.noBorder.matchOptional(workspaceRule.noBorder, PRIORITY_WORKSPACE_RULE);
|
|
|
|
m_sWindowData.noRounding.matchOptional(workspaceRule.noRounding, PRIORITY_WORKSPACE_RULE);
|
|
|
|
m_sWindowData.noShadow.matchOptional(workspaceRule.noShadow, PRIORITY_WORKSPACE_RULE);
|
2023-08-17 10:13:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int CWindow::getRealBorderSize() {
|
2024-07-11 16:10:42 +02:00
|
|
|
if (m_sWindowData.noBorder.valueOrDefault() || (m_pWorkspace && m_bIsFullscreen && (m_pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL)))
|
2023-08-17 10:13:19 +02:00
|
|
|
return 0;
|
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
static auto PBORDERSIZE = CConfigValue<Hyprlang::INT>("general:border_size");
|
2024-02-18 16:00:34 +01:00
|
|
|
|
2024-07-11 16:10:42 +02:00
|
|
|
return m_sWindowData.borderSize.valueOr(*PBORDERSIZE);
|
2023-08-17 10:13:19 +02:00
|
|
|
}
|
2023-09-28 22:48:33 +02:00
|
|
|
|
|
|
|
bool CWindow::canBeTorn() {
|
2024-07-11 16:10:42 +02:00
|
|
|
return m_sWindowData.tearing.valueOr(m_bTearingHint);
|
2023-09-28 22:48:33 +02:00
|
|
|
}
|
2023-12-11 17:51:10 +01:00
|
|
|
|
|
|
|
bool CWindow::shouldSendFullscreenState() {
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto MODE = m_pWorkspace->m_efFullscreenMode;
|
2024-02-17 17:21:06 +01:00
|
|
|
return m_bDontSendFullscreen ? false : (m_bFakeFullscreenState || (m_bIsFullscreen && (MODE == FULLSCREEN_FULL)));
|
2023-12-11 17:51:10 +01:00
|
|
|
}
|
2023-12-23 22:30:49 +01:00
|
|
|
|
|
|
|
void CWindow::setSuspended(bool suspend) {
|
|
|
|
if (suspend == m_bSuspended)
|
|
|
|
return;
|
|
|
|
|
2024-05-11 00:28:33 +02:00
|
|
|
if (m_bIsX11 || !m_pXDGSurface->toplevel)
|
2023-12-23 22:30:49 +01:00
|
|
|
return;
|
|
|
|
|
2024-05-11 00:28:33 +02:00
|
|
|
m_pXDGSurface->toplevel->setSuspeneded(suspend);
|
2023-12-29 00:26:23 +01:00
|
|
|
m_bSuspended = suspend;
|
2023-12-23 22:30:49 +01:00
|
|
|
}
|
2024-03-14 19:25:28 +01:00
|
|
|
|
|
|
|
bool CWindow::visibleOnMonitor(CMonitor* pMonitor) {
|
|
|
|
CBox wbox = {m_vRealPosition.value(), m_vRealSize.value()};
|
|
|
|
|
2024-05-05 23:18:10 +02:00
|
|
|
return !wbox.intersection({pMonitor->vecPosition, pMonitor->vecSize}).empty();
|
2024-03-14 19:25:28 +01:00
|
|
|
}
|
2024-03-19 03:52:52 +01:00
|
|
|
|
|
|
|
void CWindow::setAnimationsToMove() {
|
|
|
|
auto* const PANIMCFG = g_pConfigManager->getAnimationPropertyConfig("windowsMove");
|
|
|
|
m_vRealPosition.setConfig(PANIMCFG);
|
|
|
|
m_vRealSize.setConfig(PANIMCFG);
|
|
|
|
m_bAnimatingIn = false;
|
|
|
|
}
|
2024-03-25 17:08:55 +01:00
|
|
|
|
2024-03-31 03:14:26 +02:00
|
|
|
void CWindow::onWorkspaceAnimUpdate() {
|
|
|
|
// clip box for animated offsets
|
|
|
|
if (!m_bIsFloating || m_bPinned || m_bIsFullscreen) {
|
|
|
|
m_vFloatingOffset = Vector2D(0, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector2D offset;
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PWORKSPACE = m_pWorkspace;
|
2024-03-31 03:14:26 +02:00
|
|
|
if (!PWORKSPACE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const auto PWSMON = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
|
|
|
if (!PWSMON)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const auto WINBB = getFullWindowBoundingBox();
|
|
|
|
if (PWORKSPACE->m_vRenderOffset.value().x != 0) {
|
|
|
|
const auto PROGRESS = PWORKSPACE->m_vRenderOffset.value().x / PWSMON->vecSize.x;
|
|
|
|
|
|
|
|
if (WINBB.x < PWSMON->vecPosition.x)
|
|
|
|
offset.x += (PWSMON->vecPosition.x - WINBB.x) * PROGRESS;
|
|
|
|
|
|
|
|
if (WINBB.x + WINBB.width > PWSMON->vecPosition.x + PWSMON->vecSize.x)
|
|
|
|
offset.x += (WINBB.x + WINBB.width - PWSMON->vecPosition.x - PWSMON->vecSize.x) * PROGRESS;
|
|
|
|
} else if (PWORKSPACE->m_vRenderOffset.value().y != 0) {
|
|
|
|
const auto PROGRESS = PWORKSPACE->m_vRenderOffset.value().y / PWSMON->vecSize.y;
|
|
|
|
|
|
|
|
if (WINBB.y < PWSMON->vecPosition.y)
|
|
|
|
offset.y += (PWSMON->vecPosition.y - WINBB.y) * PROGRESS;
|
|
|
|
|
|
|
|
if (WINBB.y + WINBB.height > PWSMON->vecPosition.y + PWSMON->vecSize.y)
|
|
|
|
offset.y += (WINBB.y + WINBB.height - PWSMON->vecPosition.y - PWSMON->vecSize.y) * PROGRESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_vFloatingOffset = offset;
|
|
|
|
}
|
|
|
|
|
2024-03-25 17:08:55 +01:00
|
|
|
int CWindow::popupsCount() {
|
2024-05-11 00:28:33 +02:00
|
|
|
if (m_bIsX11)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
int no = -1;
|
|
|
|
m_pPopupHead->breadthfirst([](CPopup* p, void* d) { *((int*)d) += 1; }, &no);
|
|
|
|
return no;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CWindow::surfacesCount() {
|
2024-03-25 17:08:55 +01:00
|
|
|
if (m_bIsX11)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
int no = 0;
|
2024-06-08 10:07:59 +02:00
|
|
|
m_pWLSurface->resource()->breadthfirst([](SP<CWLSurfaceResource> r, const Vector2D& offset, void* d) { *((int*)d) += 1; }, &no);
|
2024-03-25 17:08:55 +01:00
|
|
|
return no;
|
|
|
|
}
|
2024-04-02 21:32:39 +02:00
|
|
|
|
|
|
|
int CWindow::workspaceID() {
|
|
|
|
return m_pWorkspace ? m_pWorkspace->m_iID : m_iLastWorkspace;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CWindow::onSpecialWorkspace() {
|
|
|
|
return m_pWorkspace ? m_pWorkspace->m_bIsSpecialWorkspace : g_pCompositor->isWorkspaceSpecial(m_iLastWorkspace);
|
|
|
|
}
|
2024-04-23 02:28:20 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
//
|
2024-04-23 02:40:03 +02:00
|
|
|
std::string environFile = "/proc/" + std::to_string(PID) + "/environ";
|
|
|
|
std::ifstream ifs(environFile, std::ios::binary);
|
2024-04-23 02:28:20 +02:00
|
|
|
|
|
|
|
if (!ifs.good())
|
|
|
|
return {};
|
|
|
|
|
|
|
|
std::vector<char> buffer;
|
|
|
|
size_t needle = 0;
|
|
|
|
buffer.resize(512, '\0');
|
|
|
|
while (ifs.read(buffer.data() + needle, 512)) {
|
|
|
|
buffer.resize(buffer.size() + 512, '\0');
|
|
|
|
needle += 512;
|
|
|
|
}
|
|
|
|
|
2024-05-24 20:40:15 +02:00
|
|
|
if (needle <= 1)
|
|
|
|
return {};
|
|
|
|
|
2024-04-23 02:28:20 +02:00
|
|
|
std::replace(buffer.begin(), buffer.end() - 1, '\0', '\n');
|
|
|
|
|
2024-05-24 20:40:15 +02:00
|
|
|
CVarList envs(std::string{buffer.data(), buffer.size() - 1}, 0, '\n', true);
|
2024-04-23 02:28:20 +02:00
|
|
|
|
|
|
|
for (auto& e : envs) {
|
|
|
|
if (!e.contains('='))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
const auto EQ = e.find_first_of('=');
|
|
|
|
results[e.substr(0, EQ)] = e.substr(EQ + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return results;
|
|
|
|
}
|
2024-04-25 01:58:40 +02:00
|
|
|
|
2024-05-08 02:31:16 +02:00
|
|
|
void CWindow::activate(bool force) {
|
2024-05-11 00:28:33 +02:00
|
|
|
if (g_pCompositor->m_pLastWindow == m_pSelf)
|
|
|
|
return;
|
|
|
|
|
2024-04-25 01:58:40 +02:00
|
|
|
static auto PFOCUSONACTIVATE = CConfigValue<Hyprlang::INT>("misc:focus_on_activate");
|
|
|
|
|
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"urgent", std::format("{:x}", (uintptr_t)this)});
|
2024-04-27 13:43:12 +02:00
|
|
|
EMIT_HOOK_EVENT("urgent", m_pSelf.lock());
|
2024-04-25 01:58:40 +02:00
|
|
|
|
|
|
|
m_bIsUrgent = true;
|
|
|
|
|
2024-07-11 16:10:42 +02:00
|
|
|
if (!force && (!m_sWindowData.focusOnActivate.valueOr(*PFOCUSONACTIVATE) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE_FOCUSONLY) || (m_eSuppressedEvents & SUPPRESS_ACTIVATE)))
|
2024-04-25 01:58:40 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (m_bIsFloating)
|
2024-04-27 13:43:12 +02:00
|
|
|
g_pCompositor->changeWindowZOrder(m_pSelf.lock(), true);
|
2024-04-25 01:58:40 +02:00
|
|
|
|
2024-04-27 13:43:12 +02:00
|
|
|
g_pCompositor->focusWindow(m_pSelf.lock());
|
2024-06-07 19:52:15 +02:00
|
|
|
warpCursor();
|
2024-04-25 01:58:40 +02:00
|
|
|
}
|
2024-05-11 00:28:33 +02:00
|
|
|
|
|
|
|
void CWindow::onUpdateState() {
|
2024-05-25 22:43:51 +02:00
|
|
|
std::optional<bool> requestsFS = m_pXDGSurface ? m_pXDGSurface->toplevel->state.requestsFullscreen : m_pXWaylandSurface->state.requestsFullscreen;
|
|
|
|
std::optional<bool> requestsMX = m_pXDGSurface ? m_pXDGSurface->toplevel->state.requestsMaximize : m_pXWaylandSurface->state.requestsMaximize;
|
2024-05-11 00:28:33 +02:00
|
|
|
|
2024-05-25 22:43:51 +02:00
|
|
|
if (requestsFS.has_value() && !(m_eSuppressedEvents & SUPPRESS_FULLSCREEN)) {
|
|
|
|
bool fs = requestsFS.value();
|
2024-05-11 00:28:33 +02:00
|
|
|
|
2024-05-25 22:43:51 +02:00
|
|
|
if (fs != m_bIsFullscreen && m_bIsMapped)
|
2024-05-11 00:28:33 +02:00
|
|
|
g_pCompositor->setWindowFullscreen(m_pSelf.lock(), fs, FULLSCREEN_FULL);
|
|
|
|
|
2024-05-25 22:43:51 +02:00
|
|
|
if (!m_bIsMapped)
|
2024-05-11 00:28:33 +02:00
|
|
|
m_bWantsInitialFullscreen = fs;
|
|
|
|
}
|
|
|
|
|
2024-05-25 22:43:51 +02:00
|
|
|
if (requestsMX.has_value() && !(m_eSuppressedEvents & SUPPRESS_MAXIMIZE)) {
|
|
|
|
bool fs = requestsMX.value();
|
2024-05-11 00:28:33 +02:00
|
|
|
|
2024-05-25 22:43:51 +02:00
|
|
|
if (fs != m_bIsFullscreen && m_bIsMapped)
|
2024-05-11 00:28:33 +02:00
|
|
|
g_pCompositor->setWindowFullscreen(m_pSelf.lock(), fs, FULLSCREEN_MAXIMIZED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CWindow::onUpdateMeta() {
|
|
|
|
const auto NEWTITLE = fetchTitle();
|
2024-05-28 23:37:24 +02:00
|
|
|
bool doUpdate = false;
|
2024-05-11 00:28:33 +02:00
|
|
|
|
|
|
|
if (m_szTitle != NEWTITLE) {
|
|
|
|
m_szTitle = NEWTITLE;
|
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"windowtitle", std::format("{:x}", (uintptr_t)this)});
|
2024-07-13 16:21:32 +02:00
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"windowtitlev2", std::format("{:x},{}", (uintptr_t)this, m_szTitle)});
|
2024-05-11 00:28:33 +02:00
|
|
|
EMIT_HOOK_EVENT("windowTitle", m_pSelf.lock());
|
|
|
|
|
|
|
|
if (m_pSelf == g_pCompositor->m_pLastWindow) { // if it's the active, let's post an event to update others
|
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", m_szClass + "," + m_szTitle});
|
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", std::format("{:x}", (uintptr_t)this)});
|
|
|
|
EMIT_HOOK_EVENT("activeWindow", m_pSelf.lock());
|
|
|
|
}
|
|
|
|
|
|
|
|
Debug::log(LOG, "Window {:x} set title to {}", (uintptr_t)this, m_szTitle);
|
2024-05-28 23:37:24 +02:00
|
|
|
doUpdate = true;
|
2024-05-11 00:28:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const auto NEWCLASS = fetchClass();
|
|
|
|
if (m_szClass != NEWCLASS) {
|
|
|
|
m_szClass = NEWCLASS;
|
|
|
|
|
|
|
|
if (m_pSelf == g_pCompositor->m_pLastWindow) { // if it's the active, let's post an event to update others
|
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", m_szClass + "," + m_szTitle});
|
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", std::format("{:x}", (uintptr_t)this)});
|
|
|
|
EMIT_HOOK_EVENT("activeWindow", m_pSelf.lock());
|
|
|
|
}
|
|
|
|
|
2024-05-28 23:37:24 +02:00
|
|
|
Debug::log(LOG, "Window {:x} set class to {}", (uintptr_t)this, m_szClass);
|
|
|
|
doUpdate = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (doUpdate) {
|
2024-05-11 00:28:33 +02:00
|
|
|
updateDynamicRules();
|
|
|
|
g_pCompositor->updateWindowAnimatedDecorationValues(m_pSelf.lock());
|
|
|
|
updateToplevel();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string CWindow::fetchTitle() {
|
|
|
|
if (!m_bIsX11) {
|
|
|
|
if (m_pXDGSurface && m_pXDGSurface->toplevel)
|
|
|
|
return m_pXDGSurface->toplevel->state.title;
|
|
|
|
} else {
|
2024-05-25 22:43:51 +02:00
|
|
|
if (m_pXWaylandSurface)
|
|
|
|
return m_pXWaylandSurface->state.title;
|
2024-05-11 00:28:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string CWindow::fetchClass() {
|
|
|
|
if (!m_bIsX11) {
|
|
|
|
if (m_pXDGSurface && m_pXDGSurface->toplevel)
|
|
|
|
return m_pXDGSurface->toplevel->state.appid;
|
|
|
|
} else {
|
2024-05-25 22:43:51 +02:00
|
|
|
if (m_pXWaylandSurface)
|
|
|
|
return m_pXWaylandSurface->state.appid;
|
2024-05-11 00:28:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
void CWindow::onAck(uint32_t serial) {
|
|
|
|
const auto SERIAL = std::find_if(m_vPendingSizeAcks.rbegin(), m_vPendingSizeAcks.rend(), [serial](const auto& e) { return e.first == serial; });
|
|
|
|
|
|
|
|
if (SERIAL == m_vPendingSizeAcks.rend())
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_pPendingSizeAck = *SERIAL;
|
|
|
|
std::erase_if(m_vPendingSizeAcks, [&](const auto& el) { return el.first <= SERIAL->first; });
|
2024-05-25 22:43:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CWindow::onResourceChangeX11() {
|
2024-06-08 10:07:59 +02:00
|
|
|
if (m_pXWaylandSurface->surface && !m_pWLSurface->resource())
|
|
|
|
m_pWLSurface->assign(m_pXWaylandSurface->surface.lock(), m_pSelf.lock());
|
|
|
|
else if (!m_pXWaylandSurface->surface && m_pWLSurface->resource())
|
|
|
|
m_pWLSurface->unassign();
|
2024-05-25 22:43:51 +02:00
|
|
|
|
|
|
|
// update metadata as well,
|
|
|
|
// could be first assoc and we need to catch the class
|
|
|
|
onUpdateMeta();
|
|
|
|
|
2024-06-08 10:07:59 +02:00
|
|
|
Debug::log(LOG, "xwayland window {:x} -> association to {:x}", (uintptr_t)m_pXWaylandSurface.get(), (uintptr_t)m_pWLSurface->resource().get());
|
2024-05-25 22:43:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CWindow::onX11Configure(CBox box) {
|
|
|
|
|
|
|
|
if (!m_pXWaylandSurface->surface || !m_pXWaylandSurface->mapped || !m_bIsMapped) {
|
|
|
|
m_pXWaylandSurface->configure(box);
|
|
|
|
m_vPendingReportedSize = box.size();
|
|
|
|
m_vReportedSize = box.size();
|
|
|
|
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR)
|
|
|
|
m_fX11SurfaceScaledBy = PMONITOR->scale;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_pHyprRenderer->damageWindow(m_pSelf.lock());
|
|
|
|
|
|
|
|
if (!m_bIsFloating || m_bIsFullscreen || g_pInputManager->currentlyDraggedWindow == m_pSelf) {
|
|
|
|
g_pXWaylandManager->setWindowSize(m_pSelf.lock(), m_vRealSize.goal(), true);
|
|
|
|
g_pInputManager->refocus();
|
|
|
|
g_pHyprRenderer->damageWindow(m_pSelf.lock());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (box.size() > Vector2D{1, 1})
|
|
|
|
setHidden(false);
|
|
|
|
else
|
|
|
|
setHidden(true);
|
|
|
|
|
|
|
|
const auto LOGICALPOS = g_pXWaylandManager->xwaylandToWaylandCoords(box.pos());
|
|
|
|
|
|
|
|
m_vRealPosition.setValueAndWarp(LOGICALPOS);
|
|
|
|
m_vRealSize.setValueAndWarp(box.size());
|
|
|
|
|
|
|
|
static auto PXWLFORCESCALEZERO = CConfigValue<Hyprlang::INT>("xwayland:force_zero_scaling");
|
|
|
|
if (*PXWLFORCESCALEZERO) {
|
|
|
|
if (const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); PMONITOR) {
|
|
|
|
m_vRealSize.setValueAndWarp(m_vRealSize.goal() / PMONITOR->scale);
|
|
|
|
m_fX11SurfaceScaledBy = PMONITOR->scale;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_vPosition = m_vRealPosition.value();
|
|
|
|
m_vSize = m_vRealSize.value();
|
|
|
|
|
|
|
|
m_pXWaylandSurface->configure(box);
|
|
|
|
|
|
|
|
m_vPendingReportedSize = box.size();
|
|
|
|
m_vReportedSize = box.size();
|
|
|
|
|
|
|
|
updateWindowDecos();
|
|
|
|
|
|
|
|
if (!g_pCompositor->isWorkspaceVisible(m_pWorkspace))
|
|
|
|
return; // further things are only for visible windows
|
|
|
|
|
|
|
|
m_pWorkspace = g_pCompositor->getMonitorFromVector(m_vRealPosition.value() + m_vRealSize.value() / 2.f)->activeWorkspace;
|
|
|
|
|
|
|
|
g_pCompositor->changeWindowZOrder(m_pSelf.lock(), true);
|
|
|
|
|
|
|
|
m_bCreatedOverFullscreen = true;
|
|
|
|
|
|
|
|
g_pHyprRenderer->damageWindow(m_pSelf.lock());
|
|
|
|
}
|
2024-06-07 19:52:15 +02:00
|
|
|
|
|
|
|
void CWindow::warpCursor() {
|
|
|
|
static auto PERSISTENTWARPS = CConfigValue<Hyprlang::INT>("cursor:persistent_warps");
|
|
|
|
const auto coords = m_vRelativeCursorCoordsOnLastWarp;
|
|
|
|
m_vRelativeCursorCoordsOnLastWarp.x = -1; // reset m_vRelativeCursorCoordsOnLastWarp
|
|
|
|
|
|
|
|
if (*PERSISTENTWARPS && coords.x > 0 && coords.y > 0 && coords < m_vSize) // don't warp cursor outside the window
|
|
|
|
g_pCompositor->warpCursorTo(m_vPosition + coords);
|
|
|
|
else
|
|
|
|
g_pCompositor->warpCursorTo(middle());
|
|
|
|
}
|
2024-06-15 18:20:09 +02:00
|
|
|
|
|
|
|
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 || (*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& w : g_pCompositor->m_vWindows) {
|
|
|
|
if (!w->m_bIsMapped || w->isHidden())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (w->getPID() == currentPid)
|
|
|
|
candidates.push_back(w);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(*PSWALLOWREGEX).empty())
|
|
|
|
std::erase_if(candidates, [&](const auto& other) { return !std::regex_match(other->m_szClass, std::regex(*PSWALLOWREGEX)); });
|
|
|
|
|
|
|
|
if (candidates.size() <= 0)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
if (!(*PSWALLOWEXREGEX).empty())
|
|
|
|
std::erase_if(candidates, [&](const auto& other) { return std::regex_match(other->m_szTitle, std::regex(*PSWALLOWEXREGEX)); });
|
|
|
|
|
|
|
|
if (candidates.size() <= 0)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
if (candidates.size() == 1)
|
|
|
|
return candidates.at(0);
|
|
|
|
|
|
|
|
// walk up the focus history and find the last focused
|
|
|
|
for (auto& w : g_pCompositor->m_vWindowFocusHistory) {
|
|
|
|
if (!w)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (std::find(candidates.begin(), candidates.end(), w.lock()) != candidates.end())
|
|
|
|
return w.lock();
|
|
|
|
}
|
|
|
|
|
|
|
|
// if none are found (??) then just return the first one
|
|
|
|
return candidates.at(0);
|
|
|
|
}
|
2024-07-11 16:10:42 +02:00
|
|
|
|
|
|
|
void CWindow::unsetWindowData(eOverridePriority priority) {
|
|
|
|
for (auto const& element : g_pConfigManager->mbWindowProperties) {
|
|
|
|
element.second(m_pSelf.lock())->unset(priority);
|
|
|
|
}
|
|
|
|
for (auto const& element : g_pConfigManager->miWindowProperties) {
|
|
|
|
element.second(m_pSelf.lock())->unset(priority);
|
|
|
|
}
|
|
|
|
}
|