From ffacd2efd1ca7fdf364a519c9d8d8644da28412b Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 25 Sep 2023 15:00:19 +0100 Subject: [PATCH 001/513] hyprctl: fix crash in unsafe state with activeworkspace fixes #3419 --- src/debug/HyprCtl.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index f37b24e6..0aafe664 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -228,8 +228,15 @@ static std::string getWorkspaceData(CWorkspace* w, HyprCtl::eHyprCtlOutputFormat } std::string activeWorkspaceRequest(HyprCtl::eHyprCtlOutputFormat format) { + if (!g_pCompositor->m_pLastMonitor) + return "unsafe state"; + std::string result = ""; auto w = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace); + + if (!w) + return "internal error"; + return getWorkspaceData(w, format); } From 6d7dc70f663891ef39dcfb8ba8e5ff643b4d9ed8 Mon Sep 17 00:00:00 2001 From: "Cascade aka. Isoheptane" <38118922+Isoheptane@users.noreply.github.com> Date: Thu, 28 Sep 2023 02:49:30 +0800 Subject: [PATCH 002/513] input: Add map to region options for tablets (#3425) * Add region remap for tablets * Fix code style --- src/config/ConfigManager.cpp | 16 ++++++++++++++++ src/config/ConfigManager.hpp | 3 +++ src/managers/input/InputManager.cpp | 6 ++++++ 3 files changed, 25 insertions(+) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 2eaee318..7556776e 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -222,6 +222,8 @@ void CConfigManager::setDefaultVars() { configValues["input:touchdevice:output"].strValue = STRVAL_EMPTY; configValues["input:tablet:transform"].intValue = 0; configValues["input:tablet:output"].strValue = STRVAL_EMPTY; + configValues["input:tablet:region_position"].vecValue = Vector2D(); + configValues["input:tablet:region_size"].vecValue = Vector2D(); configValues["binds:pass_mouse_when_bound"].intValue = 0; configValues["binds:scroll_event_delay"].intValue = 300; @@ -278,6 +280,8 @@ void CConfigManager::setDeviceDefaultVars(const std::string& dev) { cfgValues["transform"].intValue = 0; cfgValues["output"].strValue = STRVAL_EMPTY; cfgValues["enabled"].intValue = 1; // only for mice / touchpads + cfgValues["region_position"].vecValue = Vector2D(); // only for tablets + cfgValues["region_size"].vecValue = Vector2D(); // only for tablets } void CConfigManager::setDefaultAnimationVars() { @@ -1737,6 +1741,10 @@ float CConfigManager::getFloat(const std::string& v) { return getConfigValueSafe(v).floatValue; } +Vector2D CConfigManager::getVec(const std::string& v) { + return getConfigValueSafe(v).vecValue; +} + std::string CConfigManager::getString(const std::string& v) { auto VAL = getConfigValueSafe(v).strValue; @@ -1754,6 +1762,10 @@ float CConfigManager::getDeviceFloat(const std::string& dev, const std::string& return getConfigValueSafeDevice(dev, v, fallback).floatValue; } +Vector2D CConfigManager::getDeviceVec(const std::string& dev, const std::string& v, const std::string& fallback) { + return getConfigValueSafeDevice(dev, v, fallback).vecValue; +} + std::string CConfigManager::getDeviceString(const std::string& dev, const std::string& v, const std::string& fallback) { auto VAL = getConfigValueSafeDevice(dev, v, fallback).strValue; @@ -1771,6 +1783,10 @@ void CConfigManager::setFloat(const std::string& v, float val) { configValues[v].floatValue = val; } +void CConfigManager::setVec(const std::string& v, Vector2D val) { + configValues[v].vecValue = val; +} + void CConfigManager::setString(const std::string& v, const std::string& val) { configValues[v].strValue = val; } diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 3d545bc4..390079d3 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -83,13 +83,16 @@ class CConfigManager { int getInt(const std::string&); float getFloat(const std::string&); + Vector2D getVec(const std::string&); std::string getString(const std::string&); void setFloat(const std::string&, float); void setInt(const std::string&, int); + void setVec(const std::string&, Vector2D); void setString(const std::string&, const std::string&); int getDeviceInt(const std::string&, const std::string&, const std::string& fallback = ""); float getDeviceFloat(const std::string&, const std::string&, const std::string& fallback = ""); + Vector2D getDeviceVec(const std::string&, const std::string&, const std::string& fallback = ""); std::string getDeviceString(const std::string&, const std::string&, const std::string& fallback = ""); bool deviceConfigExists(const std::string&); bool shouldBlurLS(const std::string&); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index ab633bc5..02ccfd1b 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1444,6 +1444,12 @@ void CInputManager::setTabletConfigs() { wlr_cursor_map_input_to_output(g_pCompositor->m_sWLRCursor, t.wlrDevice, PMONITOR->output); wlr_cursor_map_input_to_region(g_pCompositor->m_sWLRCursor, t.wlrDevice, nullptr); } + + const auto REGION_POS = g_pConfigManager->getDeviceVec(t.name, "region_position", "input:tablet:region_position"); + const auto REGION_SIZE = g_pConfigManager->getDeviceVec(t.name, "region_size", "input:tablet:region_size"); + const auto REGION = wlr_box{REGION_POS.x, REGION_POS.y, REGION_SIZE.x, REGION_SIZE.y}; + if (!wlr_box_empty(®ION)) + wlr_cursor_map_input_to_region(g_pCompositor->m_sWLRCursor, t.wlrDevice, ®ION); } } } From 1f4eab176ef8978e022ea9367f9b7fb61273f163 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Thu, 28 Sep 2023 17:49:33 +0100 Subject: [PATCH 003/513] layout: don't discard fullscreen on new tiling --- src/Compositor.cpp | 6 ++++-- src/events/Windows.cpp | 11 ----------- src/helpers/Workspace.hpp | 5 +++-- src/layout/DwindleLayout.cpp | 11 ++--------- src/layout/DwindleLayout.hpp | 2 +- src/layout/IHyprLayout.hpp | 10 ++++++---- src/layout/MasterLayout.cpp | 7 ------- src/layout/MasterLayout.hpp | 5 +++-- 8 files changed, 19 insertions(+), 38 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 4ddac879..0672a543 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2148,14 +2148,16 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode const auto PWORKSPACE = getWorkspaceByID(pWindow->m_iWorkspaceID); + const auto MODE = mode == FULLSCREEN_INVALID ? PWORKSPACE->m_efFullscreenMode : mode; + if (PWORKSPACE->m_bHasFullscreenWindow && on) { Debug::log(LOG, "Rejecting fullscreen ON on a fullscreen workspace"); return; } - g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(pWindow, mode, on); + g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(pWindow, MODE, on); - g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->m_bIsFullscreen && mode == FULLSCREEN_FULL); + g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->m_bIsFullscreen && MODE == FULLSCREEN_FULL); pWindow->updateDynamicRules(); updateWindowAnimatedDecorationValues(pWindow); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index d0ae4ae8..f726b224 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -263,13 +263,6 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->applyDynamicRule(r); } - CWindow* pFullscreenWindow = nullptr; - if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFloating) { - const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); - pFullscreenWindow = PFULLWINDOW; - g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, PWORKSPACE->m_efFullscreenMode); - } - PWINDOW->updateSpecialRenderData(); // disallow tiled pinned @@ -543,10 +536,6 @@ void Events::listener_mapWindow(void* owner, void* data) { } } - if (pFullscreenWindow && workspaceSilent) { - g_pCompositor->setWindowFullscreen(pFullscreenWindow, true, PWORKSPACE->m_efFullscreenMode); - } - // recheck idle inhibitors g_pInputManager->recheckIdleInhibitorStatus(); diff --git a/src/helpers/Workspace.hpp b/src/helpers/Workspace.hpp index 07b5694c..2e810b9a 100644 --- a/src/helpers/Workspace.hpp +++ b/src/helpers/Workspace.hpp @@ -4,9 +4,10 @@ #include #include "../defines.hpp" -enum eFullscreenMode : uint8_t +enum eFullscreenMode : int8_t { - FULLSCREEN_FULL = 0, + FULLSCREEN_INVALID = -1, + FULLSCREEN_FULL = 0, FULLSCREEN_MAXIMIZED }; diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index fae4af52..1ce47d96 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -291,13 +291,6 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire return; } - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); - - if (PWORKSPACE->m_bHasFullscreenWindow) { - const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); - g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, FULLSCREEN_FULL); - } - // last fail-safe to avoid duplicate fullscreens if ((!OPENINGON || OPENINGON->pWindow == pWindow) && getNodesOnWorkspace(PNODE->workspaceID) > 1) { for (auto& node : m_lDwindleNodesData) { @@ -481,8 +474,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire NEWPARENT->recalcSizePosRecursive(false, horizontalOverride, verticalOverride); - applyNodeDataToWindow(PNODE); - applyNodeDataToWindow(OPENINGON); + recalculateMonitor(pWindow->m_iMonitorID); + pWindow->applyGroupRules(); } diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp index 993f8cb7..47818536 100644 --- a/src/layout/DwindleLayout.hpp +++ b/src/layout/DwindleLayout.hpp @@ -9,7 +9,7 @@ #include class CHyprDwindleLayout; -enum eFullscreenMode : uint8_t; +enum eFullscreenMode : int8_t; struct SDwindleNodeData { SDwindleNodeData* pParent = nullptr; diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index 15acbc1d..32f95a22 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -13,9 +13,10 @@ struct SLayoutMessageHeader { CWindow* pWindow = nullptr; }; -enum eFullscreenMode : uint8_t; +enum eFullscreenMode : int8_t; -enum eRectCorner { +enum eRectCorner +{ CORNER_NONE = 0, CORNER_TOPLEFT, CORNER_TOPRIGHT, @@ -23,9 +24,10 @@ enum eRectCorner { CORNER_BOTTOMLEFT }; -enum eDirection { +enum eDirection +{ DIRECTION_DEFAULT = -1, - DIRECTION_UP = 0, + DIRECTION_UP = 0, DIRECTION_RIGHT, DIRECTION_DOWN, DIRECTION_LEFT diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index c1dd37dc..624ded2a 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -167,13 +167,6 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc } } - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); - - if (PWORKSPACE->m_bHasFullscreenWindow) { - const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); - g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, FULLSCREEN_FULL); - } - // recalc recalculateMonitor(pWindow->m_iMonitorID); } diff --git a/src/layout/MasterLayout.hpp b/src/layout/MasterLayout.hpp index aa201505..f220bd7b 100644 --- a/src/layout/MasterLayout.hpp +++ b/src/layout/MasterLayout.hpp @@ -7,10 +7,11 @@ #include #include -enum eFullscreenMode : uint8_t; +enum eFullscreenMode : int8_t; //orientation determines which side of the screen the master area resides -enum eOrientation : uint8_t { +enum eOrientation : uint8_t +{ ORIENTATION_LEFT = 0, ORIENTATION_TOP, ORIENTATION_RIGHT, From 280f385cf8743456e0d205e40c8c7c439e8e6d1e Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Thu, 28 Sep 2023 18:05:55 +0100 Subject: [PATCH 004/513] makefile: fix permissions on files --- Makefile | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Makefile b/Makefile index 518df327..0f3fa398 100644 --- a/Makefile +++ b/Makefile @@ -3,18 +3,22 @@ PREFIX = /usr/local legacyrenderer: cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` + chmod 711 ./build/Hyprland legacyrendererdebug: cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` + chmod 711 ./build/Hyprland release: cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` + chmod 711 ./build/Hyprland debug: cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -S . -B ./build -G Ninja cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` + chmod 711 ./build/Hyprland clear: rm -rf build @@ -35,8 +39,11 @@ install: $(MAKE) fixwlr cd ./subprojects/wlroots && meson setup build/ --buildtype=release && ninja -C build/ && mkdir -p ${PREFIX}/lib/ && cp ./build/libwlroots.so.12032 ${PREFIX}/lib/ || echo "Could not install libwlroots to ${PREFIX}/lib/libwlroots.so.12032" cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B./build -G Ninja && cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` && cd ../.. + chmod -R 777 subprojects/udis86 + chmod -R 777 subprojects/wlroots $(MAKE) release $(MAKE) -C hyprctl all + chmod 711 ./build/hyprctl/hyprctl mkdir -p ${PREFIX}/share/wayland-sessions mkdir -p ${PREFIX}/bin @@ -89,8 +96,12 @@ config: ninja -C subprojects/wlroots/build/ install + chmod -R 777 subprojects/wlroots + cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja && cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` + chmod -R 777 subprojects/udis86 + pluginenv: cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja && cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` From eab5967ef49bfba29b31b91d71b035ead55aaf74 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Thu, 28 Sep 2023 18:06:07 +0100 Subject: [PATCH 005/513] deps: update wlroots --- subprojects/wlroots | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/wlroots b/subprojects/wlroots index 98a745d9..c2aa7fd9 160000 --- a/subprojects/wlroots +++ b/subprojects/wlroots @@ -1 +1 @@ -Subproject commit 98a745d926d8048bc30aef11b421df207a01c279 +Subproject commit c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e From 08595f839b6c1fb02edd490ff2c2da4e0db7b226 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 28 Sep 2023 17:06:54 +0000 Subject: [PATCH 006/513] [gha] Nix: update wlroots --- flake.lock | 8 ++++---- flake.nix | 2 +- subprojects/wlroots.wrap | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 8a52cc43..524ca010 100644 --- a/flake.lock +++ b/flake.lock @@ -67,18 +67,18 @@ "flake": false, "locked": { "host": "gitlab.freedesktop.org", - "lastModified": 1695277534, - "narHash": "sha256-LEIUGXvKR5DYFQUTavC3yifcObvG4XZUUHfxXmu8nEM=", + "lastModified": 1695919988, + "narHash": "sha256-4RBgIZHaVqH0m1POnfzYRzwCWxifIKH4xQ0kCn2LGkA=", "owner": "wlroots", "repo": "wlroots", - "rev": "98a745d926d8048bc30aef11b421df207a01c279", + "rev": "c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e", "type": "gitlab" }, "original": { "host": "gitlab.freedesktop.org", "owner": "wlroots", "repo": "wlroots", - "rev": "98a745d926d8048bc30aef11b421df207a01c279", + "rev": "c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e", "type": "gitlab" } }, diff --git a/flake.nix b/flake.nix index 91135803..d2eb35c5 100644 --- a/flake.nix +++ b/flake.nix @@ -12,7 +12,7 @@ host = "gitlab.freedesktop.org"; owner = "wlroots"; repo = "wlroots"; - rev = "98a745d926d8048bc30aef11b421df207a01c279"; + rev = "c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e"; flake = false; }; diff --git a/subprojects/wlroots.wrap b/subprojects/wlroots.wrap index 31fddb18..04427ba6 100644 --- a/subprojects/wlroots.wrap +++ b/subprojects/wlroots.wrap @@ -1,7 +1,7 @@ [wrap-git] directory = wlroots url = https://gitlab.freedesktop.org/wlroots/wlroots.git -revision = 98a745d926d8048bc30aef11b421df207a01c279 +revision = c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e depth = 1 diff_files = wlroots-meson-build.patch From d48c11cc3f12dc12315008b5574be6455238db7b Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Thu, 28 Sep 2023 20:02:00 +0100 Subject: [PATCH 007/513] input: minor constraint fixes Better adjust to constraints that do not set a hint. Fixes #3436 --- src/helpers/WLClasses.hpp | 11 +++--- src/managers/input/InputManager.cpp | 56 ++++++++++++++--------------- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index d66ebdfd..d33af797 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -168,18 +168,19 @@ struct SConstraint { bool active = false; - bool hintSet = false; - Vector2D positionHint = {-1, -1}; // the position hint, but will be set to the current cursor pos if not set. + bool hintSet = false; + Vector2D positionHint = {-1, -1}; // the position hint, but will use cursorPosOnActivate if unset + Vector2D cursorPosOnActivate = {-1, -1}; DYNLISTENER(setConstraintRegion); DYNLISTENER(destroyConstraint); - CRegion getLogicCoordsRegion(); + CRegion getLogicCoordsRegion(); Vector2D getLogicConstraintPos(); Vector2D getLogicConstraintSize(); - bool operator==(const SConstraint& b) const { - return constraint == b.constraint; + bool operator==(const SConstraint& b) const { + return constraint == b.constraint; } }; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 02ccfd1b..beb55c5d 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1207,24 +1207,30 @@ void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* co return; const auto MOUSECOORDS = getMouseCoordsInternal(); + const auto PCONSTRAINT = constraintFromWlr(constraint); pMouse->hyprListener_commitConstraint.removeCallback(); - if (pMouse->currentConstraint) { - if (constraint) { - const auto PCONSTRAINT = constraintFromWlr(constraint); - if (constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) { - PCONSTRAINT->hintSet = true; - PCONSTRAINT->positionHint = {constraint->current.cursor_hint.x, constraint->current.cursor_hint.y}; - } - - if (constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT && constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED) - warpMouseToConstraintMiddle(PCONSTRAINT); - } - + if (pMouse->currentConstraint) wlr_pointer_constraint_v1_send_deactivated(pMouse->currentConstraint); + + if (const auto PWINDOW = g_pCompositor->getWindowFromSurface(constraint->surface); PWINDOW) { + const auto RELATIVETO = PWINDOW->m_bIsX11 ? + (PWINDOW->m_bIsMapped ? PWINDOW->m_vRealPosition.goalv() : + g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y})) : + PWINDOW->m_vRealPosition.goalv(); + + PCONSTRAINT->cursorPosOnActivate = MOUSECOORDS - RELATIVETO; } + if (constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) { + PCONSTRAINT->hintSet = true; + PCONSTRAINT->positionHint = {constraint->current.cursor_hint.x, constraint->current.cursor_hint.y}; + } + + if (constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT && constraint->type == WLR_POINTER_CONSTRAINT_V1_LOCKED) + warpMouseToConstraintMiddle(PCONSTRAINT); + pMouse->currentConstraint = constraint; pMouse->constraintActive = true; @@ -1236,7 +1242,7 @@ void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* co // warp to the constraint recheckConstraint(pMouse); - constraintFromWlr(constraint)->active = true; + PCONSTRAINT->active = true; wlr_pointer_constraint_v1_send_activated(pMouse->currentConstraint); @@ -1253,23 +1259,17 @@ void CInputManager::warpMouseToConstraintMiddle(SConstraint* pConstraint) { const auto PWINDOW = g_pCompositor->getWindowFromSurface(pConstraint->constraint->surface); if (PWINDOW) { - const auto RELATIVETO = PWINDOW->m_bIsX11 ? - (PWINDOW->m_bIsMapped ? PWINDOW->m_vRealPosition.goalv() : - g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y})) : - PWINDOW->m_vRealPosition.goalv(); + const auto RELATIVETO = pConstraint->getLogicConstraintPos(); const auto HINTSCALE = PWINDOW->m_fX11SurfaceScaledBy; - if (pConstraint->hintSet) { - wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, RELATIVETO.x + pConstraint->positionHint.x / HINTSCALE, RELATIVETO.y + pConstraint->positionHint.y / HINTSCALE); - wlr_seat_pointer_warp(pConstraint->constraint->seat, pConstraint->constraint->current.cursor_hint.x, pConstraint->constraint->current.cursor_hint.y); - } else { - const auto RELATIVESIZE = PWINDOW->m_bIsX11 ? - (PWINDOW->m_bIsMapped ? PWINDOW->m_vRealSize.goalv() : - g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->width, PWINDOW->m_uSurface.xwayland->height})) : - PWINDOW->m_vRealSize.goalv(); + auto HINT = pConstraint->hintSet ? pConstraint->positionHint : pConstraint->cursorPosOnActivate; - wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, RELATIVETO.x + RELATIVESIZE.x / 2.f, RELATIVETO.y + RELATIVESIZE.y / 2.f); - wlr_seat_pointer_warp(pConstraint->constraint->seat, RELATIVESIZE.x / 2.f, RELATIVESIZE.y / 2.f); + if (HINT == Vector2D{-1, -1}) + HINT = pConstraint->getLogicConstraintSize() / 2.f; + + if (HINT != Vector2D{-1, -1}) { + wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, RELATIVETO.x + HINT.x / HINTSCALE, RELATIVETO.y + HINT.y / HINTSCALE); + wlr_seat_pointer_warp(pConstraint->constraint->seat, pConstraint->constraint->current.cursor_hint.x, pConstraint->constraint->current.cursor_hint.y); } } } @@ -1597,7 +1597,7 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) { wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; eBorderIconDirection direction = BORDERICON_NONE; wlr_box boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE), - box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; + box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; if (!wlr_box_contains_point(&boxFullGrabInput, mouseCoords.x, mouseCoords.y) || (!m_lCurrentlyHeldButtons.empty() && !currentlyDraggedWindow)) { direction = BORDERICON_NONE; From 1e513e25d5645260a2ebdfbe8dbf3b8df487339c Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Thu, 28 Sep 2023 20:10:21 +0100 Subject: [PATCH 008/513] makefile: fix wrong path in chmod --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0f3fa398..64cb1518 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,7 @@ install: chmod -R 777 subprojects/wlroots $(MAKE) release $(MAKE) -C hyprctl all - chmod 711 ./build/hyprctl/hyprctl + chmod 711 ./hyprctl/hyprctl mkdir -p ${PREFIX}/share/wayland-sessions mkdir -p ${PREFIX}/bin From 88b63a00b68350d6d001445357a2582ab5975f9c Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Thu, 28 Sep 2023 21:48:33 +0100 Subject: [PATCH 009/513] renderer: Tearing implementation (#3441) --- CMakeLists.txt | 1 + protocols/meson.build | 1 + src/Compositor.cpp | 11 ++- src/Compositor.hpp | 1 + src/Window.cpp | 12 +++ src/Window.hpp | 10 +- src/config/ConfigManager.cpp | 9 +- src/debug/HyprCtl.cpp | 2 + src/events/Events.hpp | 3 + src/events/Misc.cpp | 40 ++++++++ src/events/Monitors.cpp | 10 ++ src/helpers/Monitor.cpp | 2 + src/helpers/Monitor.hpp | 7 ++ src/helpers/SubsurfaceTree.cpp | 9 ++ src/helpers/WLClasses.hpp | 13 ++- src/includes.hpp | 1 + src/managers/input/InputManager.cpp | 3 +- src/render/Renderer.cpp | 137 +++++++++++++++++++--------- src/render/Renderer.hpp | 20 ++-- 19 files changed, 231 insertions(+), 61 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a52c798a..b3bc5526 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -218,5 +218,6 @@ protocol("stable/xdg-shell/xdg-shell.xml" "xdg-shell" false) protocol("unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml" "linux-dmabuf-unstable-v1" false) protocol("unstable/xdg-output/xdg-output-unstable-v1.xml" "xdg-output-unstable-v1" false) protocol("staging/fractional-scale/fractional-scale-v1.xml" "fractional-scale-v1" false) +protocol("staging/tearing-control/tearing-control-v1.xml" "tearing-control-v1" false) protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v1" false) protocol("staging/cursor-shape/cursor-shape-v1.xml" "cursor-shape-v1" false) diff --git a/protocols/meson.build b/protocols/meson.build index 60ae20cb..cc111e98 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -25,6 +25,7 @@ protocols = [ [wl_protocol_dir, 'unstable/xdg-output/xdg-output-unstable-v1.xml'], [wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml'], [wl_protocol_dir, 'staging/cursor-shape/cursor-shape-v1.xml'], + [wl_protocol_dir, 'staging/tearing-control/tearing-control-v1.xml'], ['wlr-foreign-toplevel-management-unstable-v1.xml'], ['wlr-layer-shell-unstable-v1.xml'], ['wlr-output-power-management-unstable-v1.xml'], diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 0672a543..1cb378db 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -257,6 +257,8 @@ void CCompositor::initServer() { m_sWLRCursorShapeMgr = wlr_cursor_shape_manager_v1_create(m_sWLDisplay, 1); + m_sWLRTearingControlMgr = wlr_tearing_control_manager_v1_create(m_sWLDisplay, 1); + if (!m_sWLRHeadlessBackend) { Debug::log(CRIT, "Couldn't create the headless backend"); throwError("wlr_headless_backend_create() failed!"); @@ -315,6 +317,7 @@ void CCompositor::initAllSignals() { addWLSignal(&m_sWLRSessionLockMgr->events.new_lock, &Events::listen_newSessionLock, m_sWLRSessionLockMgr, "SessionLockMgr"); addWLSignal(&m_sWLRGammaCtrlMgr->events.set_gamma, &Events::listen_setGamma, m_sWLRGammaCtrlMgr, "GammaCtrlMgr"); addWLSignal(&m_sWLRCursorShapeMgr->events.request_set_shape, &Events::listen_setCursorShape, m_sWLRCursorShapeMgr, "CursorShapeMgr"); + addWLSignal(&m_sWLRTearingControlMgr->events.new_object, &Events::listen_newTearingHint, m_sWLRTearingControlMgr, "TearingControlMgr"); if (m_sWRLDRMLeaseMgr) addWLSignal(&m_sWRLDRMLeaseMgr->events.request, &Events::listen_leaseRequest, &m_sWRLDRMLeaseMgr, "DRM"); @@ -2475,7 +2478,13 @@ int CCompositor::getNewSpecialID() { } void CCompositor::performUserChecks() { - // empty + const auto atomicEnv = getenv("WLR_DRM_NO_ATOMIC"); + const auto atomicEnvStr = std::string(atomicEnv ? atomicEnv : ""); + if (g_pConfigManager->getInt("general:allow_tearing") == 1 && atomicEnvStr != "1") { + g_pHyprNotificationOverlay->addNotification("You have enabled tearing, but immediate presentations are not available on your configuration. Try adding " + "env = WLR_DRM_NO_ATOMIC,1 to your config.", + CColor(0), 15000, ICON_WARNING); + } } void CCompositor::moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorkspace) { diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 06d15c3c..99839b06 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -85,6 +85,7 @@ class CCompositor { wlr_session_lock_manager_v1* m_sWLRSessionLockMgr; wlr_gamma_control_manager_v1* m_sWLRGammaCtrlMgr; wlr_cursor_shape_manager_v1* m_sWLRCursorShapeMgr; + wlr_tearing_control_manager_v1* m_sWLRTearingControlMgr; // ------------------------------------------------- // std::string m_szWLDisplaySocket = ""; diff --git a/src/Window.cpp b/src/Window.cpp index 4ee40dff..9055101e 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -414,6 +414,11 @@ void CWindow::onUnmap() { if (PMONITOR && PMONITOR->specialWorkspaceID == m_iWorkspaceID) PMONITOR->setSpecialWorkspace(nullptr); } + + const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + + if (PMONITOR && PMONITOR->solitaryClient == this) + PMONITOR->solitaryClient = nullptr; } void CWindow::onMap() { @@ -492,6 +497,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { } else if (r.szRule == "opaque") { if (!m_sAdditionalConfigData.forceOpaqueOverridden) m_sAdditionalConfigData.forceOpaque = true; + } else if (r.szRule == "immediate") { + m_sAdditionalConfigData.forceTearing = true; } else if (r.szRule.find("rounding") == 0) { try { m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1)); @@ -580,6 +587,7 @@ void CWindow::updateDynamicRules() { m_sAdditionalConfigData.borderSize = -1; m_sAdditionalConfigData.keepAspectRatio = false; m_sAdditionalConfigData.xray = -1; + m_sAdditionalConfigData.forceTearing = false; const auto WINDOWRULES = g_pConfigManager->getMatchingRules(this); for (auto& r : WINDOWRULES) { @@ -925,3 +933,7 @@ int CWindow::getRealBorderSize() { return g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; } + +bool CWindow::canBeTorn() { + return (m_sAdditionalConfigData.forceTearing.toUnderlying() || m_bTearingHint) && g_pHyprRenderer->m_bTearingEnvSatisfied; +} diff --git a/src/Window.hpp b/src/Window.hpp index 81b6156f..dd16fdcb 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -11,14 +11,16 @@ #include "macros.hpp" #include "managers/XWaylandManager.hpp" -enum eIdleInhibitMode { +enum eIdleInhibitMode +{ IDLEINHIBIT_NONE = 0, IDLEINHIBIT_ALWAYS, IDLEINHIBIT_FULLSCREEN, IDLEINHIBIT_FOCUS }; -enum eGroupRules { +enum eGroupRules +{ // effective only during first map, except for _ALWAYS variant GROUP_NONE = 0, GROUP_SET = 1 << 0, // Open as new group or add to focused group @@ -138,6 +140,7 @@ struct SWindowAdditionalConfigData { CWindowOverridableVar keepAspectRatio = false; CWindowOverridableVar xray = -1; // -1 means unset, takes precedence over the renderdata one CWindowOverridableVar borderSize = -1; // -1 means unset, takes precedence over the renderdata one + CWindowOverridableVar forceTearing = false; }; struct SWindowRule { @@ -317,6 +320,8 @@ class CWindow { } m_sGroupData; uint16_t m_eGroupRules = GROUP_NONE; + bool m_bTearingHint = false; + // For the list lookup bool operator==(const CWindow& rhs) { return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize && @@ -348,6 +353,7 @@ class CWindow { Vector2D middle(); bool opaque(); float rounding(); + bool canBeTorn(); int getRealBorderSize(); void updateSpecialRenderData(); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 7556776e..fc7a9e3e 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -87,6 +87,7 @@ void CConfigManager::setDefaultVars() { configValues["general:extend_border_grab_area"].intValue = 15; configValues["general:hover_icon_on_border"].intValue = 1; configValues["general:layout"].strValue = "dwindle"; + configValues["general:allow_tearing"].intValue = 0; configValues["misc:disable_hyprland_logo"].intValue = 0; configValues["misc:disable_splash_rendering"].intValue = 0; @@ -279,7 +280,7 @@ void CConfigManager::setDeviceDefaultVars(const std::string& dev) { cfgValues["scroll_button_lock"].intValue = 0; cfgValues["transform"].intValue = 0; cfgValues["output"].strValue = STRVAL_EMPTY; - cfgValues["enabled"].intValue = 1; // only for mice / touchpads + cfgValues["enabled"].intValue = 1; // only for mice / touchpads cfgValues["region_position"].vecValue = Vector2D(); // only for tablets cfgValues["region_size"].vecValue = Vector2D(); // only for tablets } @@ -912,7 +913,7 @@ bool windowRuleValid(const std::string& RULE) { RULE != "nomaximizerequest" && RULE != "fakefullscreen" && RULE != "nomaxsize" && RULE != "pin" && RULE != "noanim" && RULE != "dimaround" && RULE != "windowdance" && RULE != "maximize" && RULE != "keepaspectratio" && RULE.find("animation") != 0 && RULE.find("rounding") != 0 && RULE.find("workspace") != 0 && RULE.find("bordercolor") != 0 && RULE != "forcergbx" && RULE != "noinitialfocus" && RULE != "stayfocused" && RULE.find("bordersize") != 0 && RULE.find("xray") != 0 && - RULE.find("center") != 0 && RULE.find("group") != 0); + RULE.find("center") != 0 && RULE.find("group") != 0 && RULE != "immediate"); } bool layerRuleValid(const std::string& RULE) { @@ -1244,7 +1245,7 @@ void CConfigManager::handleSource(const std::string& command, const std::string& int linenum = 1; if (ifs.is_open()) { auto configCurrentPathBackup = configCurrentPath; - + while (std::getline(ifs, line)) { // Read line by line. try { @@ -1265,7 +1266,7 @@ void CConfigManager::handleSource(const std::string& command, const std::string& } ifs.close(); - + configCurrentPath = configCurrentPathBackup; } } diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 0aafe664..8eced97d 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1009,6 +1009,8 @@ std::string dispatchSetProp(std::string request) { PWINDOW->m_sSpecialRenderData.borderSize.forceSetIgnoreLocked(configStringToInt(VAL), lock); } else if (PROP == "keepaspectratio") { PWINDOW->m_sAdditionalConfigData.keepAspectRatio.forceSetIgnoreLocked(configStringToInt(VAL), lock); + } else if (PROP == "immediate") { + PWINDOW->m_sAdditionalConfigData.forceTearing.forceSetIgnoreLocked(configStringToInt(VAL), lock); } else { return "prop not found"; } diff --git a/src/events/Events.hpp b/src/events/Events.hpp index f89032ea..fc68880e 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -174,4 +174,7 @@ namespace Events { // Cursor shape LISTENER(setCursorShape); + + // Tearing hints + LISTENER(newTearingHint); }; diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp index d4e7bad9..1df4be3a 100644 --- a/src/events/Misc.cpp +++ b/src/events/Misc.cpp @@ -237,3 +237,43 @@ void Events::listener_setCursorShape(wl_listener* listener, void* data) { g_pInputManager->processMouseRequest(E); } + +void Events::listener_newTearingHint(wl_listener* listener, void* data) { + const auto TCTL = (wlr_tearing_control_v1*)data; + + const auto PWINDOW = g_pCompositor->getWindowFromSurface(TCTL->surface); + + if (!PWINDOW) { + Debug::log(ERR, "Tearing hint {} was attached to an unknown surface", (uintptr_t)data); + return; + } + + Debug::log(LOG, "New tearing hint for window {} at {}", PWINDOW, (uintptr_t)data); + + const auto NEWCTRL = g_pHyprRenderer->m_vTearingControllers.emplace_back(std::make_unique()).get(); + NEWCTRL->pWlrHint = (wlr_tearing_control_v1*)data; + + NEWCTRL->hyprListener_destroy.initCallback( + &NEWCTRL->pWlrHint->events.destroy, + [&](void* owner, void* data) { + Debug::log(LOG, "Destroyed {} tearing hint", (uintptr_t)((STearingController*)owner)->pWlrHint); + + std::erase_if(g_pHyprRenderer->m_vTearingControllers, [&](const auto& other) { return other.get() == owner; }); + }, + NEWCTRL, "TearingController"); + + NEWCTRL->hyprListener_set.initCallback( + &NEWCTRL->pWlrHint->events.set_hint, + [&](void* owner, void* data) { + const auto TEARINGHINT = (STearingController*)owner; + + const auto PWINDOW = g_pCompositor->getWindowFromSurface(TEARINGHINT->pWlrHint->surface); + + if (PWINDOW) { + PWINDOW->m_bTearingHint = TEARINGHINT->pWlrHint->hint; + + Debug::log(LOG, "Hint {} (window {}) set tearing hint to {}", (uintptr_t)TEARINGHINT->pWlrHint, PWINDOW, (uint32_t)TEARINGHINT->pWlrHint->hint); + } + }, + NEWCTRL, "TearingController"); +} diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 947f9e7f..d006c2f2 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -149,6 +149,14 @@ void Events::listener_monitorFrame(void* owner, void* data) { if (!PMONITOR->m_bEnabled) return; + if (PMONITOR->ignoreNextFlipEvent) { + Debug::log(LOG, "Ignore next flip event for {}", PMONITOR->szName); + PMONITOR->ignoreNextFlipEvent = false; + return; + } + + PMONITOR->renderingFromVblankEvent = true; + static auto* const PENABLERAT = &g_pConfigManager->getConfigValuePtr("misc:render_ahead_of_time")->intValue; static auto* const PRATSAFE = &g_pConfigManager->getConfigValuePtr("misc:render_ahead_safezone")->intValue; @@ -181,6 +189,8 @@ void Events::listener_monitorFrame(void* owner, void* data) { } else { g_pHyprRenderer->renderMonitor(PMONITOR); } + + PMONITOR->renderingFromVblankEvent = false; } void Events::listener_monitorDestroy(void* owner, void* data) { diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index dd9580d1..0d0b2a64 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -40,6 +40,8 @@ void CMonitor::onConnect(bool noRule) { hyprListener_monitorCommit.initCallback(&output->events.commit, &Events::listener_monitorCommit, this); hyprListener_monitorBind.initCallback(&output->events.bind, &Events::listener_monitorBind, this); + canTear = wlr_backend_is_drm(output->backend); // tearing only works on drm + if (m_bEnabled) { wlr_output_enable(output, 1); wlr_output_commit(output); diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 93f345ba..f8b8554c 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -81,6 +81,13 @@ class CMonitor { CRegion lastFrameDamage; // stores last frame damage + // for tearing + CWindow* solitaryClient = nullptr; + bool canTear = false; + bool nextRenderTorn = false; + bool ignoreNextFlipEvent = false; + bool renderingFromVblankEvent = false; + // for the special workspace. 0 means not open. int specialWorkspaceID = 0; diff --git a/src/helpers/SubsurfaceTree.cpp b/src/helpers/SubsurfaceTree.cpp index 5e3e9e67..5b86f928 100644 --- a/src/helpers/SubsurfaceTree.cpp +++ b/src/helpers/SubsurfaceTree.cpp @@ -245,6 +245,15 @@ void Events::listener_commitSubsurface(void* owner, void* data) { if (pNode->pSurface && pNode->pSurface->exists()) g_pHyprRenderer->damageSurface(pNode->pSurface->wlr(), lx, ly, SCALE); + + if (pNode->pWindowOwner) { + // tearing: if solitary, redraw it. This still might be a single surface window + const auto PMONITOR = g_pCompositor->getMonitorFromID(pNode->pWindowOwner->m_iMonitorID); + if (PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->canBeTorn() && PMONITOR->canTear) { + PMONITOR->nextRenderTorn = true; + g_pHyprRenderer->renderMonitor(PMONITOR); + } + } } void Events::listener_destroySubsurface(void* owner, void* data) { diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index d33af797..e8647426 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -180,7 +180,7 @@ struct SConstraint { Vector2D getLogicConstraintSize(); bool operator==(const SConstraint& b) const { - return constraint == b.constraint; + return constraint == b.constraint; } }; @@ -393,3 +393,14 @@ struct SSwitchDevice { return pWlrDevice == other.pWlrDevice; } }; + +struct STearingController { + wlr_tearing_control_v1* pWlrHint = nullptr; + + DYNLISTENER(set); + DYNLISTENER(destroy); + + bool operator==(const STearingController& other) { + return pWlrHint == other.pWlrHint; + } +}; diff --git a/src/includes.hpp b/src/includes.hpp index c81ee9fe..1205f55c 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -105,6 +105,7 @@ extern "C" { #include #include #include +#include #include diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index beb55c5d..e790bf7f 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -118,7 +118,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (*PZOOMFACTOR != 1.f) g_pHyprRenderer->damageMonitor(PMONITOR); - g_pCompositor->scheduleFrameForMonitor(PMONITOR); + if (!PMONITOR->solitaryClient) // if there is a solitary client we can't schedule a frame here, this will completely fuck up drm + g_pCompositor->scheduleFrameForMonitor(PMONITOR); CWindow* forcedFocus = m_pForcedFocus; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 6dcf0b44..982edd4b 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -3,6 +3,13 @@ #include "linux-dmabuf-unstable-v1-protocol.h" #include "../helpers/Region.hpp" +CHyprRenderer::CHyprRenderer() { + const auto ENV = getenv("WLR_DRM_NO_ATOMIC"); + + if (ENV && std::string(ENV) == "1") + m_bTearingEnvSatisfied = true; +} + void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { const auto TEXTURE = wlr_surface_get_texture(surface); const auto RDATA = (SRenderData*)data; @@ -702,51 +709,12 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { if (!wlr_output_is_direct_scanout_allowed(pMonitor->output)) return false; - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pMonitor->activeWorkspace); - - if (!PWORKSPACE || !PWORKSPACE->m_bHasFullscreenWindow || g_pInputManager->m_sDrag.drag || g_pCompositor->m_sSeat.exclusiveClient || pMonitor->specialWorkspaceID) - return false; - - const auto PCANDIDATE = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); + const auto PCANDIDATE = pMonitor->solitaryClient; if (!PCANDIDATE) - return false; // ???? - - if (PCANDIDATE->m_fAlpha.fl() != 1.f || PCANDIDATE->m_fActiveInactiveAlpha.fl() != 1.f || PWORKSPACE->m_fAlpha.fl() != 1.f) return false; - if (PCANDIDATE->m_vRealSize.vec() != pMonitor->vecSize || PCANDIDATE->m_vRealPosition.vec() != pMonitor->vecPosition || PCANDIDATE->m_vRealPosition.isBeingAnimated() || - PCANDIDATE->m_vRealSize.isBeingAnimated()) - return false; - - if (!pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY].empty()) - return false; - - for (auto& topls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { - if (topls->alpha.fl() != 0.f) - return false; - } - - // check if it did not open any subsurfaces or shit - int surfaceCount = 0; - if (PCANDIDATE->m_bIsX11) { - surfaceCount = 1; - - // check opaque - if (PCANDIDATE->m_uSurface.xwayland->has_alpha) - return false; - } else { - wlr_xdg_surface_for_each_surface(PCANDIDATE->m_uSurface.xdg, countSubsurfacesIter, &surfaceCount); - wlr_xdg_surface_for_each_popup_surface(PCANDIDATE->m_uSurface.xdg, countSubsurfacesIter, &surfaceCount); - - if (!PCANDIDATE->m_uSurface.xdg->surface->opaque) - return false; - } - - if (surfaceCount != 1) - return false; - - const auto PSURFACE = PCANDIDATE->m_pWLSurface.wlr(); + const auto PSURFACE = g_pXWaylandManager->getWindowSurface(PCANDIDATE); if (!PSURFACE || PSURFACE->current.scale != pMonitor->output->scale || PSURFACE->current.transform != pMonitor->output->transform) return false; @@ -754,9 +722,8 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { // finally, we should be GTG. wlr_output_attach_buffer(pMonitor->output, &PSURFACE->buffer->base); - if (!wlr_output_test(pMonitor->output)) { + if (!wlr_output_test(pMonitor->output)) return false; - } timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -790,6 +757,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { static auto* const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue; static auto* const PBACKGROUNDCOLOR = &g_pConfigManager->getConfigValuePtr("misc:background_color")->intValue; static auto* const PANIMENABLED = &g_pConfigManager->getConfigValuePtr("animations:enabled")->intValue; + static auto* const PTEARINGENABLED = &g_pConfigManager->getConfigValuePtr("general:allow_tearing")->intValue; static int damageBlinkCleanup = 0; // because double-buffered @@ -876,8 +844,38 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } } - // Direct scanout first - if (!*PNODIRECTSCANOUT) { + // tearing and DS first + bool shouldTear = false; + bool canTear = *PTEARINGENABLED && g_pHyprOpenGL->m_RenderData.mouseZoomFactor == 1.0; + recheckSolitaryForMonitor(pMonitor); + if (pMonitor->nextRenderTorn) { + pMonitor->nextRenderTorn = false; + + if (!*PTEARINGENABLED) { + Debug::log(WARN, "Tearing commit requested but the master switch general:allow_tearing is off, ignoring"); + return; + } + + if (g_pHyprOpenGL->m_RenderData.mouseZoomFactor != 1.0) { + Debug::log(WARN, "Tearing commit requested but scale factor is not 1, ignoring"); + return; + } + + if (!pMonitor->canTear) { + Debug::log(WARN, "Tearing commit requested but monitor doesn't support it, ignoring"); + return; + } + + if (pMonitor->solitaryClient) + shouldTear = true; + } else { + // if this is a non-tearing commit, and we are in a state where we should tear + // then this is a vblank commit that we should ignore + if (canTear && pMonitor->solitaryClient && pMonitor->canTear && pMonitor->solitaryClient->canBeTorn() && pMonitor->renderingFromVblankEvent) + return; + } + + if (!*PNODIRECTSCANOUT && !shouldTear) { if (attemptDirectScanout(pMonitor)) { return; } else if (m_pLastScanout) { @@ -1061,6 +1059,8 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { EMIT_HOOK_EVENT("render", RENDER_POST); + pMonitor->output->pending.tearing_page_flip = shouldTear; + if (!wlr_output_commit(pMonitor->output)) { if (UNLOCK_SC) wlr_output_lock_software_cursors(pMonitor->output, false); @@ -1068,6 +1068,9 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { return; } + if (shouldTear) + pMonitor->ignoreNextFlipEvent = true; + wlr_damage_ring_rotate(&pMonitor->damage); if (UNLOCK_SC) @@ -1986,3 +1989,47 @@ bool CHyprRenderer::canSkipBackBufferClear(CMonitor* pMonitor) { return false; } + +void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { + pMonitor->solitaryClient = nullptr; // reset it, if we find one it will be set. + + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pMonitor->activeWorkspace); + + if (!PWORKSPACE || !PWORKSPACE->m_bHasFullscreenWindow || g_pInputManager->m_sDrag.drag || g_pCompositor->m_sSeat.exclusiveClient || pMonitor->specialWorkspaceID) + return; + + const auto PCANDIDATE = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); + + if (!PCANDIDATE) + return; // ???? + + if (!PCANDIDATE->opaque()) + return; + + if (PCANDIDATE->m_vRealSize.vec() != pMonitor->vecSize || PCANDIDATE->m_vRealPosition.vec() != pMonitor->vecPosition || PCANDIDATE->m_vRealPosition.isBeingAnimated() || + PCANDIDATE->m_vRealSize.isBeingAnimated()) + return; + + if (!pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY].empty()) + return; + + for (auto& topls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { + if (topls->alpha.fl() != 0.f) + return; + } + + // check if it did not open any subsurfaces or shit + int surfaceCount = 0; + if (PCANDIDATE->m_bIsX11) { + surfaceCount = 1; + } else { + wlr_xdg_surface_for_each_surface(PCANDIDATE->m_uSurface.xdg, countSubsurfacesIter, &surfaceCount); + wlr_xdg_surface_for_each_popup_surface(PCANDIDATE->m_uSurface.xdg, countSubsurfacesIter, &surfaceCount); + } + + if (surfaceCount != 1) + Debug::log(LOG, "fuf: >1 surf"); + + // found one! + pMonitor->solitaryClient = PCANDIDATE; +} diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index f0e19c38..2b437b00 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -33,6 +33,8 @@ struct SSessionLockSurface; class CHyprRenderer { public: + CHyprRenderer(); + void renderMonitor(CMonitor* pMonitor); void outputMgrApplyTest(wlr_output_configuration_v1*, bool); void arrangeLayersForMonitor(const int&); @@ -53,6 +55,7 @@ class CHyprRenderer { void renderLockscreen(CMonitor* pMonitor, timespec* now); void setOccludedForBackLayers(CRegion& region, CWorkspace* pWorkspace); bool canSkipBackBufferClear(CMonitor* pMonitor); + void recheckSolitaryForMonitor(CMonitor* pMonitor); bool m_bWindowRequestedCursorHide = false; bool m_bBlockSurfaceFeedback = false; @@ -61,19 +64,22 @@ class CHyprRenderer { CMonitor* m_pMostHzMonitor = nullptr; bool m_bDirectScanoutBlocked = false; bool m_bSoftwareCursorsLocked = false; + bool m_bTearingEnvSatisfied = false; DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&); - bool attemptDirectScanout(CMonitor*); - void setWindowScanoutMode(CWindow*); - void initiateManualCrash(); + bool attemptDirectScanout(CMonitor*); + void setWindowScanoutMode(CWindow*); + void initiateManualCrash(); - bool m_bCrashingInProgress = false; - float m_fCrashingDistort = 0.5f; - wl_event_source* m_pCrashingLoop = nullptr; + bool m_bCrashingInProgress = false; + float m_fCrashingDistort = 0.5f; + wl_event_source* m_pCrashingLoop = nullptr; - CTimer m_tRenderTimer; + std::vector> m_vTearingControllers; + + CTimer m_tRenderTimer; private: void arrangeLayerArray(CMonitor*, const std::vector>&, bool, wlr_box*); From 453128ee0ef5414fc88845be06230deb908e63ce Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Thu, 28 Sep 2023 22:09:10 +0100 Subject: [PATCH 010/513] examples/readme: mention tearing --- README.md | 1 + example/hyprland.conf | 3 +++ src/config/defaultConfig.hpp | 3 +++ 3 files changed, 7 insertions(+) diff --git a/README.md b/README.md index b16019f0..10577c74 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more... - Much more QoL stuff than other wlr-based compositors - Custom bezier curves for the best animations - Powerful plugin support +- Tearing support for better gaming performance - Easily expandable and readable codebase - Fast and active development - Not scared to provide bleeding-edge features diff --git a/example/hyprland.conf b/example/hyprland.conf index 895a44f2..d28b8463 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -49,6 +49,9 @@ general { col.inactive_border = rgba(595959aa) layout = dwindle + + # Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on + allow_tearing = false } decoration { diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 1793b4a1..6c30e19c 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -58,6 +58,9 @@ general { col.inactive_border = rgba(595959aa) layout = dwindle + + # Please see https://wiki.hyprland.org/Configuring/Tearing/ before you turn this on + allow_tearing = false } decoration { From 3f09b14381e8b28dd2cc1d292763374f2d6c8484 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Thu, 28 Sep 2023 22:13:21 +0100 Subject: [PATCH 011/513] makefile: fixup permissions on installed binaries --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index 64cb1518..b980d561 100644 --- a/Makefile +++ b/Makefile @@ -49,6 +49,8 @@ install: mkdir -p ${PREFIX}/bin cp -f ./build/Hyprland ${PREFIX}/bin cp -f ./hyprctl/hyprctl ${PREFIX}/bin + chmod 711 ${PREFIX}/bin/Hyprland + chmod 711 ${PREFIX}/bin/hyprctl if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi mkdir -p ${PREFIX}/share/hyprland cp ./assets/wall_* ${PREFIX}/share/hyprland From 9cc614d096db4b7c1de6baaa055ca6f741aa4370 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Fri, 29 Sep 2023 16:38:13 +0100 Subject: [PATCH 012/513] internal: add a watchdog a watchdog will abort processing a signal if a timeout specified via debug:watchdog_timeout is reached. --- src/Compositor.cpp | 11 ++++++++ src/Compositor.hpp | 1 + src/config/ConfigManager.cpp | 1 + src/helpers/WLListener.cpp | 8 +++++- src/helpers/Watchdog.cpp | 49 ++++++++++++++++++++++++++++++++++++ src/helpers/Watchdog.hpp | 30 ++++++++++++++++++++++ 6 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 src/helpers/Watchdog.cpp create mode 100644 src/helpers/Watchdog.hpp diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 1cb378db..e114e934 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -34,6 +34,13 @@ void handleUnrecoverableSignal(int sig) { abort(); } +void handleUserSignal(int sig) { + if (sig == SIGUSR1) { + // means we have to unwind a timed out event + throw std::exception(); + } +} + CCompositor::CCompositor() { m_iHyprlandPID = getpid(); @@ -70,6 +77,8 @@ CCompositor::CCompositor() { setRandomSplash(); Debug::log(LOG, "\nCurrent splash: {}\n\n", m_szCurrentSplash); + + g_pWatchdog = std::make_unique(); } CCompositor::~CCompositor() { @@ -92,6 +101,7 @@ CCompositor::~CCompositor() { g_pAnimationManager.reset(); g_pKeybindManager.reset(); g_pHookSystem.reset(); + g_pWatchdog.reset(); } void CCompositor::setRandomSplash() { @@ -112,6 +122,7 @@ void CCompositor::initServer() { wl_event_loop_add_signal(m_sWLEventLoop, SIGTERM, handleCritSignal, nullptr); signal(SIGSEGV, handleUnrecoverableSignal); signal(SIGABRT, handleUnrecoverableSignal); + signal(SIGUSR1, handleUserSignal); //wl_event_loop_add_signal(m_sWLEventLoop, SIGINT, handleCritSignal, nullptr); initManagers(STAGE_PRIORITY); diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 99839b06..86460211 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -27,6 +27,7 @@ #include "render/OpenGL.hpp" #include "hyprerror/HyprError.hpp" #include "plugins/PluginSystem.hpp" +#include "helpers/Watchdog.hpp" enum eManagersInitStage { diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index fc7a9e3e..9f696aca 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -134,6 +134,7 @@ void CConfigManager::setDefaultVars() { configValues["debug:damage_tracking"].intValue = DAMAGE_TRACKING_FULL; configValues["debug:manual_crash"].intValue = 0; configValues["debug:suppress_errors"].intValue = 0; + configValues["debug:watchdog_timeout"].intValue = 5; configValues["decoration:rounding"].intValue = 0; configValues["decoration:blur:enabled"].intValue = 1; diff --git a/src/helpers/WLListener.cpp b/src/helpers/WLListener.cpp index 3cb051b7..cace665d 100644 --- a/src/helpers/WLListener.cpp +++ b/src/helpers/WLListener.cpp @@ -6,7 +6,13 @@ void handleWrapped(wl_listener* listener, void* data) { CHyprWLListener::SWrapper* pWrap = wl_container_of(listener, pWrap, m_sListener); - pWrap->m_pSelf->emit(data); + g_pWatchdog->startWatching(); + + try { + pWrap->m_pSelf->emit(data); + } catch (std::exception& e) { Debug::log(ERR, "Listener {} timed out and was killed by Watchdog!!!", (uintptr_t)listener); } + + g_pWatchdog->endWatching(); } CHyprWLListener::CHyprWLListener(wl_signal* pSignal, std::function callback, void* pOwner) { diff --git a/src/helpers/Watchdog.cpp b/src/helpers/Watchdog.cpp new file mode 100644 index 00000000..92f20dfb --- /dev/null +++ b/src/helpers/Watchdog.cpp @@ -0,0 +1,49 @@ +#include "Watchdog.hpp" +#include +#include "config/ConfigManager.hpp" + +CWatchdog::CWatchdog() { + m_iMainThreadPID = pthread_self(); + + m_pWatchdog = std::make_unique([this] { + static auto* const PTIMEOUT = &g_pConfigManager->getConfigValuePtr("debug:watchdog_timeout")->intValue; + + while (1337) { + std::unique_lock lk(m_mWatchdogMutex); + + if (!m_bWillWatch) + m_cvWatchdogCondition.wait(lk, [this] { return m_bNotified; }); + else { + if (m_cvWatchdogCondition.wait_for(lk, std::chrono::milliseconds((int)(*PTIMEOUT * 1000.0)), [this] { return m_bNotified; }) == false) + pthread_kill(m_iMainThreadPID, SIGUSR1); + } + + m_bWatching = false; + m_bNotified = false; + } + }); + + m_pWatchdog->detach(); +} + +void CWatchdog::startWatching() { + static auto* const PTIMEOUT = &g_pConfigManager->getConfigValuePtr("debug:watchdog_timeout")->intValue; + + if (*PTIMEOUT == 0) + return; + + m_tTriggered = std::chrono::high_resolution_clock::now(); + m_bWillWatch = true; + m_bWatching = true; + + m_bNotified = true; + m_cvWatchdogCondition.notify_all(); +} + +void CWatchdog::endWatching() { + m_bWatching = false; + m_bWillWatch = false; + + m_bNotified = true; + m_cvWatchdogCondition.notify_all(); +} \ No newline at end of file diff --git a/src/helpers/Watchdog.hpp b/src/helpers/Watchdog.hpp new file mode 100644 index 00000000..1868bd0f --- /dev/null +++ b/src/helpers/Watchdog.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include +#include + +class CWatchdog { + public: + // must be called from the main thread + CWatchdog(); + + void startWatching(); + void endWatching(); + + private: + std::chrono::high_resolution_clock::time_point m_tTriggered; + + pthread_t m_iMainThreadPID = 0; + + bool m_bWatching = false; + bool m_bWillWatch = false; + + std::unique_ptr m_pWatchdog; + std::mutex m_mWatchdogMutex; + bool m_bNotified = false; + std::condition_variable m_cvWatchdogCondition; +}; + +inline std::unique_ptr g_pWatchdog; \ No newline at end of file From 27cd7ef0c94f3dc2d2038520da8d95063ae7f2a9 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Fri, 29 Sep 2023 17:04:20 +0100 Subject: [PATCH 013/513] watchdog: initialize after config --- src/Compositor.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index e114e934..650be373 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -77,8 +77,6 @@ CCompositor::CCompositor() { setRandomSplash(); Debug::log(LOG, "\nCurrent splash: {}\n\n", m_szCurrentSplash); - - g_pWatchdog = std::make_unique(); } CCompositor::~CCompositor() { @@ -406,6 +404,7 @@ void CCompositor::initManagers(eManagersInitStage stage) { g_pLayoutManager = std::make_unique(); g_pConfigManager->init(); + g_pWatchdog = std::make_unique(); // requires config } break; case STAGE_LATE: { Debug::log(LOG, "Creating the ThreadManager!"); From ab11bd20851c5bb99f0e164ee5b0ebe3888628c0 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Fri, 29 Sep 2023 17:33:26 +0100 Subject: [PATCH 014/513] watchdog: remove thread on destroy --- src/helpers/Watchdog.cpp | 4 ++++ src/helpers/Watchdog.hpp | 1 + 2 files changed, 5 insertions(+) diff --git a/src/helpers/Watchdog.cpp b/src/helpers/Watchdog.cpp index 92f20dfb..f5d85df7 100644 --- a/src/helpers/Watchdog.cpp +++ b/src/helpers/Watchdog.cpp @@ -2,6 +2,10 @@ #include #include "config/ConfigManager.hpp" +CWatchdog::~CWatchdog() { + m_pWatchdog.reset(); +} + CWatchdog::CWatchdog() { m_iMainThreadPID = pthread_self(); diff --git a/src/helpers/Watchdog.hpp b/src/helpers/Watchdog.hpp index 1868bd0f..edbfb055 100644 --- a/src/helpers/Watchdog.hpp +++ b/src/helpers/Watchdog.hpp @@ -9,6 +9,7 @@ class CWatchdog { public: // must be called from the main thread CWatchdog(); + ~CWatchdog(); void startWatching(); void endWatching(); From a44ab7748f07ae87f944513d01685a7456c44ee0 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Fri, 29 Sep 2023 17:51:07 +0100 Subject: [PATCH 015/513] renderer: optimize render pipeline when there is a solitary client --- src/Compositor.cpp | 2 +- src/events/Monitors.cpp | 1 - src/helpers/SubsurfaceTree.cpp | 10 ++- src/managers/input/InputManager.cpp | 36 +++----- src/render/Renderer.cpp | 128 +++++++++++++++++----------- src/render/Renderer.hpp | 3 + 6 files changed, 100 insertions(+), 80 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 650be373..05875f62 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -514,7 +514,7 @@ void CCompositor::startCompositor() { throwError("The backend could not start!"); } - wlr_cursor_set_xcursor(m_sWLRCursor, m_sWLRXCursorMgr, "left_ptr"); + g_pHyprRenderer->setCursorFromName("left_ptr"); #ifdef USES_SYSTEMD if (sd_booted() > 0) diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index d006c2f2..24e7cc26 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -150,7 +150,6 @@ void Events::listener_monitorFrame(void* owner, void* data) { return; if (PMONITOR->ignoreNextFlipEvent) { - Debug::log(LOG, "Ignore next flip event for {}", PMONITOR->szName); PMONITOR->ignoreNextFlipEvent = false; return; } diff --git a/src/helpers/SubsurfaceTree.cpp b/src/helpers/SubsurfaceTree.cpp index 5b86f928..0efa4c49 100644 --- a/src/helpers/SubsurfaceTree.cpp +++ b/src/helpers/SubsurfaceTree.cpp @@ -250,8 +250,14 @@ void Events::listener_commitSubsurface(void* owner, void* data) { // tearing: if solitary, redraw it. This still might be a single surface window const auto PMONITOR = g_pCompositor->getMonitorFromID(pNode->pWindowOwner->m_iMonitorID); if (PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->canBeTorn() && PMONITOR->canTear) { - PMONITOR->nextRenderTorn = true; - g_pHyprRenderer->renderMonitor(PMONITOR); + + CRegion damageBox; + wlr_surface_get_effective_damage(pNode->pSurface->wlr(), damageBox.pixman()); + + if (!damageBox.empty()) { + PMONITOR->nextRenderTorn = true; + g_pHyprRenderer->renderMonitor(PMONITOR); + } } } } diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index e790bf7f..67b2e55d 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -307,9 +307,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (g_pHyprRenderer->m_bHasARenderedCursor) { // TODO: maybe wrap? if (m_ecbClickBehavior == CLICKMODE_KILL) - wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "crosshair"); + g_pHyprRenderer->setCursorFromName("crosshair"); else - wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "left_ptr"); + g_pHyprRenderer->setCursorFromName("left_ptr"); } m_bEmptyFocusCursorSet = true; @@ -372,18 +372,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { } } - // if we're on an input deco, reset cursor. Don't on overridden - // if (!m_bCursorImageOverridden) { - // if (!VECINRECT(m_vLastCursorPosFloored, pFoundWindow->m_vRealPosition.vec().x, pFoundWindow->m_vRealPosition.vec().y, - // pFoundWindow->m_vRealPosition.vec().x + pFoundWindow->m_vRealSize.vec().x, pFoundWindow->m_vRealPosition.vec().y + pFoundWindow->m_vRealSize.vec().y)) { - // wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "left_ptr"); - // cursorSurfaceInfo.bUsed = false; - // } else if (!cursorSurfaceInfo.bUsed) { - // cursorSurfaceInfo.bUsed = true; - // wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, cursorSurfaceInfo.pSurface, cursorSurfaceInfo.vHotspot.x, cursorSurfaceInfo.vHotspot.y); - // } - // } - if (FOLLOWMOUSE != 1 && !refocus) { if (pFoundWindow != g_pCompositor->m_pLastWindow && g_pCompositor->m_pLastWindow && ((pFoundWindow->m_bIsFloating && *PFLOATBEHAVIOR == 2) || (g_pCompositor->m_pLastWindow->m_bIsFloating != pFoundWindow->m_bIsFloating && *PFLOATBEHAVIOR != 0))) { @@ -478,7 +466,7 @@ void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_even else g_pHyprRenderer->m_bWindowRequestedCursorHide = false; - if (!cursorImageUnlocked() || !g_pHyprRenderer->shouldRenderCursor()) + if (!cursorImageUnlocked() || !g_pHyprRenderer->m_bHasARenderedCursor) return; // cursorSurfaceInfo.pSurface = e->surface; @@ -491,19 +479,19 @@ void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_even // } if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) - wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, e->surface, e->hotspot_x, e->hotspot_y); + g_pHyprRenderer->setCursorSurface(e->surface, e->hotspot_x, e->hotspot_y); } void CInputManager::processMouseRequest(wlr_cursor_shape_manager_v1_request_set_shape_event* e) { - if (!g_pHyprRenderer->shouldRenderCursor() || !cursorImageUnlocked()) + if (!g_pHyprRenderer->m_bHasARenderedCursor || !cursorImageUnlocked()) return; if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) - wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, wlr_cursor_shape_v1_name(e->shape)); + g_pHyprRenderer->setCursorFromName(wlr_cursor_shape_v1_name(e->shape)); } bool CInputManager::cursorImageUnlocked() { - if (!g_pHyprRenderer->shouldRenderCursor()) + if (!g_pHyprRenderer->m_bHasARenderedCursor) return false; if (m_ecbClickBehavior == CLICKMODE_KILL) @@ -524,7 +512,7 @@ void CInputManager::setClickMode(eClickBehaviorMode mode) { case CLICKMODE_DEFAULT: Debug::log(LOG, "SetClickMode: DEFAULT"); m_ecbClickBehavior = CLICKMODE_DEFAULT; - wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "left_ptr"); + g_pHyprRenderer->setCursorFromName("left_ptr"); break; case CLICKMODE_KILL: @@ -536,7 +524,7 @@ void CInputManager::setClickMode(eClickBehaviorMode mode) { refocus(); // set cursor - wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "crosshair"); + g_pHyprRenderer->setCursorFromName("crosshair"); break; default: break; } @@ -1507,7 +1495,7 @@ void CInputManager::destroySwitch(SSwitchDevice* pDevice) { } void CInputManager::setCursorImageUntilUnset(std::string name) { - wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, name.c_str()); + g_pHyprRenderer->setCursorFromName(name.c_str()); m_bCursorImageOverridden = true; } @@ -1517,7 +1505,7 @@ void CInputManager::unsetCursorImage() { m_bCursorImageOverridden = false; if (!g_pHyprRenderer->m_bWindowRequestedCursorHide) - wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "left_ptr"); + g_pHyprRenderer->setCursorFromName("left_ptr"); } std::string CInputManager::deviceNameToInternalString(std::string in) { @@ -1598,7 +1586,7 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) { wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; eBorderIconDirection direction = BORDERICON_NONE; wlr_box boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE), - box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; + box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; if (!wlr_box_contains_point(&boxFullGrabInput, mouseCoords.x, mouseCoords.y) || (!m_lCurrentlyHeldButtons.empty() && !currentlyDraggedWindow)) { direction = BORDERICON_NONE; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 982edd4b..fefab56b 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -967,58 +967,71 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { EMIT_HOOK_EVENT("render", RENDER_BEGIN); - if (pMonitor->isMirror()) { - g_pHyprOpenGL->blend(false); - g_pHyprOpenGL->renderMirrored(); - g_pHyprOpenGL->blend(true); - EMIT_HOOK_EVENT("render", RENDER_POST_MIRROR); + bool renderCursor = true; + + if (!pMonitor->solitaryClient) { + if (pMonitor->isMirror()) { + g_pHyprOpenGL->blend(false); + g_pHyprOpenGL->renderMirrored(); + g_pHyprOpenGL->blend(true); + EMIT_HOOK_EVENT("render", RENDER_POST_MIRROR); + renderCursor = false; + } else { + g_pHyprOpenGL->blend(false); + if (!canSkipBackBufferClear(pMonitor)) { + if (*PRENDERTEX /* inverted cfg flag */) + g_pHyprOpenGL->clear(CColor(*PBACKGROUNDCOLOR)); + else + g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper" + } + g_pHyprOpenGL->blend(true); + + wlr_box renderBox = {0, 0, (int)pMonitor->vecPixelSize.x, (int)pMonitor->vecPixelSize.y}; + renderWorkspace(pMonitor, g_pCompositor->getWorkspaceByID(pMonitor->activeWorkspace), &now, renderBox); + + renderLockscreen(pMonitor, &now); + + if (pMonitor == g_pCompositor->m_pLastMonitor) { + g_pHyprNotificationOverlay->draw(pMonitor); + g_pHyprError->draw(); + } + + // for drawing the debug overlay + if (pMonitor == g_pCompositor->m_vMonitors.front().get() && *PDEBUGOVERLAY == 1) { + startRenderOverlay = std::chrono::high_resolution_clock::now(); + g_pDebugOverlay->draw(); + endRenderOverlay = std::chrono::high_resolution_clock::now(); + } + + if (*PDAMAGEBLINK && damageBlinkCleanup == 0) { + wlr_box monrect = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}; + g_pHyprOpenGL->renderRect(&monrect, CColor(1.0, 0.0, 1.0, 100.0 / 255.0), 0); + damageBlinkCleanup = 1; + } else if (*PDAMAGEBLINK) { + damageBlinkCleanup++; + if (damageBlinkCleanup > 3) + damageBlinkCleanup = 0; + } + } } else { - g_pHyprOpenGL->blend(false); - if (!canSkipBackBufferClear(pMonitor)) { - if (*PRENDERTEX /* inverted cfg flag */) - g_pHyprOpenGL->clear(CColor(*PBACKGROUNDCOLOR)); - else - g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper" - } - g_pHyprOpenGL->blend(true); + g_pHyprRenderer->renderWindow(pMonitor->solitaryClient, pMonitor, &now, false, RENDER_PASS_MAIN /* solitary = no popups */); + } - wlr_box renderBox = {0, 0, (int)pMonitor->vecPixelSize.x, (int)pMonitor->vecPixelSize.y}; - renderWorkspace(pMonitor, g_pCompositor->getWorkspaceByID(pMonitor->activeWorkspace), &now, renderBox); + renderCursor = renderCursor && shouldRenderCursor(); - renderLockscreen(pMonitor, &now); + if (renderCursor && wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y)) { + TRACY_GPU_ZONE("RenderCursor"); - if (pMonitor == g_pCompositor->m_pLastMonitor) { - g_pHyprNotificationOverlay->draw(pMonitor); - g_pHyprError->draw(); - } + bool lockSoftware = pMonitor == g_pCompositor->getMonitorFromCursor() && *PZOOMFACTOR != 1.f; - // for drawing the debug overlay - if (pMonitor == g_pCompositor->m_vMonitors.front().get() && *PDEBUGOVERLAY == 1) { - startRenderOverlay = std::chrono::high_resolution_clock::now(); - g_pDebugOverlay->draw(); - endRenderOverlay = std::chrono::high_resolution_clock::now(); - } + if (lockSoftware) { + wlr_output_lock_software_cursors(pMonitor->output, true); + wlr_output_render_software_cursors(pMonitor->output, NULL); + wlr_output_lock_software_cursors(pMonitor->output, false); + } else + wlr_output_render_software_cursors(pMonitor->output, NULL); - if (*PDAMAGEBLINK && damageBlinkCleanup == 0) { - wlr_box monrect = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}; - g_pHyprOpenGL->renderRect(&monrect, CColor(1.0, 0.0, 1.0, 100.0 / 255.0), 0); - damageBlinkCleanup = 1; - } else if (*PDAMAGEBLINK) { - damageBlinkCleanup++; - if (damageBlinkCleanup > 3) - damageBlinkCleanup = 0; - } - - if (wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y)) { - TRACY_GPU_ZONE("RenderCursor"); - if (pMonitor == g_pCompositor->getMonitorFromCursor() && *PZOOMFACTOR != 1.f) { - wlr_output_lock_software_cursors(pMonitor->output, true); - wlr_output_render_software_cursors(pMonitor->output, NULL); - wlr_output_lock_software_cursors(pMonitor->output, false); - } else - wlr_output_render_software_cursors(pMonitor->output, NULL); - wlr_renderer_end(g_pCompositor->m_sWLRRenderer); - } + wlr_renderer_end(g_pCompositor->m_sWLRRenderer); } if (pMonitor == g_pCompositor->getMonitorFromCursor()) @@ -1050,8 +1063,6 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { if (*PDAMAGEBLINK) frameDamage.add(damage); - //wlr_output_set_damage(pMonitor->output, frameDamage.pixman()); - if (!pMonitor->mirrors.empty()) g_pHyprRenderer->damageMirrorsWith(pMonitor, frameDamage); @@ -1062,6 +1073,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { pMonitor->output->pending.tearing_page_flip = shouldTear; if (!wlr_output_commit(pMonitor->output)) { + if (UNLOCK_SC) wlr_output_lock_software_cursors(pMonitor->output, false); @@ -1858,6 +1870,17 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR return true; } +void CHyprRenderer::setCursorSurface(wlr_surface* surf, int hotspotX, int hotspotY) { + m_bCursorHasSurface = surf; + + wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, surf, hotspotX, hotspotY); +} +void CHyprRenderer::setCursorFromName(const std::string& name) { + m_bCursorHasSurface = true; + + wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, name.c_str()); +} + void CHyprRenderer::ensureCursorRenderingMode() { static auto* const PCURSORTIMEOUT = &g_pConfigManager->getConfigValuePtr("general:cursor_inactive_timeout")->intValue; static auto* const PHIDEONTOUCH = &g_pConfigManager->getConfigValuePtr("misc:hide_cursor_on_touch")->intValue; @@ -1870,7 +1893,7 @@ void CHyprRenderer::ensureCursorRenderingMode() { if (HIDE && m_bHasARenderedCursor) { m_bHasARenderedCursor = false; - wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, nullptr, 0, 0); // hide + setCursorSurface(nullptr, 0, 0); // hide Debug::log(LOG, "Hiding the cursor (timeout)"); @@ -1880,7 +1903,7 @@ void CHyprRenderer::ensureCursorRenderingMode() { m_bHasARenderedCursor = true; if (!m_bWindowRequestedCursorHide) - wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, "left_ptr"); + setCursorFromName("left_ptr"); Debug::log(LOG, "Showing the cursor (timeout)"); @@ -1893,7 +1916,7 @@ void CHyprRenderer::ensureCursorRenderingMode() { } bool CHyprRenderer::shouldRenderCursor() { - return m_bHasARenderedCursor; + return m_bHasARenderedCursor && m_bCursorHasSurface; } std::tuple CHyprRenderer::getRenderTimes(CMonitor* pMonitor) { @@ -1995,7 +2018,8 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pMonitor->activeWorkspace); - if (!PWORKSPACE || !PWORKSPACE->m_bHasFullscreenWindow || g_pInputManager->m_sDrag.drag || g_pCompositor->m_sSeat.exclusiveClient || pMonitor->specialWorkspaceID) + if (!PWORKSPACE || !PWORKSPACE->m_bHasFullscreenWindow || g_pInputManager->m_sDrag.drag || g_pCompositor->m_sSeat.exclusiveClient || pMonitor->specialWorkspaceID || + PWORKSPACE->m_fAlpha.fl() != 1.f || PWORKSPACE->m_vRenderOffset.vec() != Vector2D{}) return; const auto PCANDIDATE = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 2b437b00..e056db5c 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -56,6 +56,8 @@ class CHyprRenderer { void setOccludedForBackLayers(CRegion& region, CWorkspace* pWorkspace); bool canSkipBackBufferClear(CMonitor* pMonitor); void recheckSolitaryForMonitor(CMonitor* pMonitor); + void setCursorSurface(wlr_surface* surf, int hotspotX, int hotspotY); + void setCursorFromName(const std::string& name); bool m_bWindowRequestedCursorHide = false; bool m_bBlockSurfaceFeedback = false; @@ -94,6 +96,7 @@ class CHyprRenderer { void renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); bool m_bHasARenderedCursor = true; + bool m_bCursorHasSurface = false; friend class CHyprOpenGLImpl; friend class CToplevelExportProtocolManager; From e07e64458e4ee5c42365bb05260b85723276d1c9 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Fri, 29 Sep 2023 17:55:41 +0100 Subject: [PATCH 016/513] input: fix unused variable warn --- src/managers/input/InputManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 67b2e55d..2b43faf0 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -75,7 +75,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { static auto* const PBORDERGRABEXTEND = &g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area")->intValue; static auto* const PRESIZECURSORICON = &g_pConfigManager->getConfigValuePtr("general:hover_icon_on_border")->intValue; static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue; - const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0; const auto FOLLOWMOUSE = *PFOLLOWONDND && m_sDrag.drag ? 1 : *PFOLLOWMOUSE; From 4daa51570018900f12ede73f8bf73f6964a381bc Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Fri, 29 Sep 2023 20:05:43 +0100 Subject: [PATCH 017/513] watchdog: don't hang on exit --- src/helpers/Watchdog.cpp | 6 ++++++ src/helpers/Watchdog.hpp | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/helpers/Watchdog.cpp b/src/helpers/Watchdog.cpp index f5d85df7..2a26ee29 100644 --- a/src/helpers/Watchdog.cpp +++ b/src/helpers/Watchdog.cpp @@ -3,6 +3,9 @@ #include "config/ConfigManager.hpp" CWatchdog::~CWatchdog() { + m_bExitThread = true; + m_bNotified = true; + m_cvWatchdogCondition.notify_all(); m_pWatchdog.reset(); } @@ -22,6 +25,9 @@ CWatchdog::CWatchdog() { pthread_kill(m_iMainThreadPID, SIGUSR1); } + if (m_bExitThread) + break; + m_bWatching = false; m_bNotified = false; } diff --git a/src/helpers/Watchdog.hpp b/src/helpers/Watchdog.hpp index edbfb055..7bb499d6 100644 --- a/src/helpers/Watchdog.hpp +++ b/src/helpers/Watchdog.hpp @@ -24,7 +24,8 @@ class CWatchdog { std::unique_ptr m_pWatchdog; std::mutex m_mWatchdogMutex; - bool m_bNotified = false; + bool m_bNotified = false; + bool m_bExitThread = false; std::condition_variable m_cvWatchdogCondition; }; From 7b002d609bd8ff7d56bee4e0988c930eef4ea252 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Fri, 29 Sep 2023 20:06:20 +0100 Subject: [PATCH 018/513] input: fix warn --- src/managers/input/InputManager.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 2b43faf0..caed742e 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -71,8 +71,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { static auto* const PFLOATBEHAVIOR = &g_pConfigManager->getConfigValuePtr("input:float_switch_override_focus")->intValue; static auto* const PMOUSEFOCUSMON = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_focuses_monitor")->intValue; static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue; - static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; - static auto* const PBORDERGRABEXTEND = &g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area")->intValue; static auto* const PRESIZECURSORICON = &g_pConfigManager->getConfigValuePtr("general:hover_icon_on_border")->intValue; static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue; From 495d4f2d11f250d8a5ddde840cd0d38861f84623 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sat, 30 Sep 2023 01:35:05 +0100 Subject: [PATCH 019/513] shaders: improve border rounding --- src/render/shaders/Border.hpp | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/src/render/shaders/Border.hpp b/src/render/shaders/Border.hpp index 4e2d485d..30227804 100644 --- a/src/render/shaders/Border.hpp +++ b/src/render/shaders/Border.hpp @@ -63,33 +63,22 @@ void main() { pixCoord -= topLeft + fullSize * 0.5; pixCoord *= vec2(lessThan(pixCoord, vec2(0.0))) * -2.0 + 1.0; pixCoord -= fullSize * 0.5 - radius; + pixCoord += vec2(1.0, 1.0) / fullSize; // center the pix dont make it top-left if (min(pixCoord.x, pixCoord.y) > 0.0 && radius > 0.0) { float dist = length(pixCoord); + float h = (thick / 2.0); - if (dist > radius + 1.0 || dist < radius - thick - 1.0) - discard; - - if (primitiveMultisample == 1 && (dist > radius - 1.0 || dist < radius - thick + 1.0)) { - float distances = 0.0; - float len = length(pixCoord + vec2(0.25, 0.25)); - distances += float(len < radius && len > radius - thick); - len = length(pixCoord + vec2(0.75, 0.25)); - distances += float(len < radius && len > radius - thick); - len = length(pixCoord + vec2(0.25, 0.75)); - distances += float(len < radius && len > radius - thick); - len = length(pixCoord + vec2(0.75, 0.75)); - distances += float(len < radius && len > radius - thick); - - if (distances == 0.0) - discard; - - distances /= 4.0; - - additionalAlpha *= distances; - } else if (dist > radius || dist < radius - thick) - discard; + if (dist < radius - h) { + // lower + float normalized = clamp(smoothstep(0.0, 1.0, dist - radius + thick + 0.5), 0.0, 1.0); + additionalAlpha *= normalized; + } else { + // higher + float normalized = 1.0 - clamp(smoothstep(0.0, 1.0, dist - radius + 0.5), 0.0, 1.0); + additionalAlpha *= normalized; + } done = true; } From c298439433f9b6861c7c62ea587289ac2e4ef2f8 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sat, 30 Sep 2023 01:41:05 +0100 Subject: [PATCH 020/513] renderer: nuke multisample_edges in favor of a faster algorithm --- src/config/ConfigManager.cpp | 1 - src/render/OpenGL.cpp | 129 ++++++++++++++------------------ src/render/Shader.hpp | 1 - src/render/shaders/Border.hpp | 1 - src/render/shaders/Textures.hpp | 24 ++---- 5 files changed, 63 insertions(+), 93 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 9f696aca..cffd2587 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -150,7 +150,6 @@ void CConfigManager::setDefaultVars() { configValues["decoration:active_opacity"].floatValue = 1; configValues["decoration:inactive_opacity"].floatValue = 1; configValues["decoration:fullscreen_opacity"].floatValue = 1; - configValues["decoration:multisample_edges"].intValue = 1; configValues["decoration:no_blur_on_oversized"].intValue = 0; configValues["decoration:drop_shadow"].intValue = 1; configValues["decoration:shadow_range"].intValue = 4; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index f5a39ca7..5d513f31 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -221,32 +221,30 @@ void CHyprOpenGLImpl::bindWlrOutputFb() { } void CHyprOpenGLImpl::initShaders() { - GLuint prog = createProgram(QUADVERTSRC, QUADFRAGSRC); - m_RenderData.pCurrentMonData->m_shQUAD.program = prog; - m_RenderData.pCurrentMonData->m_shQUAD.proj = glGetUniformLocation(prog, "proj"); - m_RenderData.pCurrentMonData->m_shQUAD.color = glGetUniformLocation(prog, "color"); - m_RenderData.pCurrentMonData->m_shQUAD.posAttrib = glGetAttribLocation(prog, "pos"); - m_RenderData.pCurrentMonData->m_shQUAD.topLeft = glGetUniformLocation(prog, "topLeft"); - m_RenderData.pCurrentMonData->m_shQUAD.fullSize = glGetUniformLocation(prog, "fullSize"); - m_RenderData.pCurrentMonData->m_shQUAD.radius = glGetUniformLocation(prog, "radius"); - m_RenderData.pCurrentMonData->m_shQUAD.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample"); + GLuint prog = createProgram(QUADVERTSRC, QUADFRAGSRC); + m_RenderData.pCurrentMonData->m_shQUAD.program = prog; + m_RenderData.pCurrentMonData->m_shQUAD.proj = glGetUniformLocation(prog, "proj"); + m_RenderData.pCurrentMonData->m_shQUAD.color = glGetUniformLocation(prog, "color"); + m_RenderData.pCurrentMonData->m_shQUAD.posAttrib = glGetAttribLocation(prog, "pos"); + m_RenderData.pCurrentMonData->m_shQUAD.topLeft = glGetUniformLocation(prog, "topLeft"); + m_RenderData.pCurrentMonData->m_shQUAD.fullSize = glGetUniformLocation(prog, "fullSize"); + m_RenderData.pCurrentMonData->m_shQUAD.radius = glGetUniformLocation(prog, "radius"); - prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBA); - m_RenderData.pCurrentMonData->m_shRGBA.program = prog; - m_RenderData.pCurrentMonData->m_shRGBA.proj = glGetUniformLocation(prog, "proj"); - m_RenderData.pCurrentMonData->m_shRGBA.tex = glGetUniformLocation(prog, "tex"); - m_RenderData.pCurrentMonData->m_shRGBA.alpha = glGetUniformLocation(prog, "alpha"); - m_RenderData.pCurrentMonData->m_shRGBA.texAttrib = glGetAttribLocation(prog, "texcoord"); - m_RenderData.pCurrentMonData->m_shRGBA.posAttrib = glGetAttribLocation(prog, "pos"); - m_RenderData.pCurrentMonData->m_shRGBA.discardOpaque = glGetUniformLocation(prog, "discardOpaque"); - m_RenderData.pCurrentMonData->m_shRGBA.discardAlpha = glGetUniformLocation(prog, "discardAlpha"); - m_RenderData.pCurrentMonData->m_shRGBA.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue"); - m_RenderData.pCurrentMonData->m_shRGBA.topLeft = glGetUniformLocation(prog, "topLeft"); - m_RenderData.pCurrentMonData->m_shRGBA.fullSize = glGetUniformLocation(prog, "fullSize"); - m_RenderData.pCurrentMonData->m_shRGBA.radius = glGetUniformLocation(prog, "radius"); - m_RenderData.pCurrentMonData->m_shRGBA.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample"); - m_RenderData.pCurrentMonData->m_shRGBA.applyTint = glGetUniformLocation(prog, "applyTint"); - m_RenderData.pCurrentMonData->m_shRGBA.tint = glGetUniformLocation(prog, "tint"); + prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBA); + m_RenderData.pCurrentMonData->m_shRGBA.program = prog; + m_RenderData.pCurrentMonData->m_shRGBA.proj = glGetUniformLocation(prog, "proj"); + m_RenderData.pCurrentMonData->m_shRGBA.tex = glGetUniformLocation(prog, "tex"); + m_RenderData.pCurrentMonData->m_shRGBA.alpha = glGetUniformLocation(prog, "alpha"); + m_RenderData.pCurrentMonData->m_shRGBA.texAttrib = glGetAttribLocation(prog, "texcoord"); + m_RenderData.pCurrentMonData->m_shRGBA.posAttrib = glGetAttribLocation(prog, "pos"); + m_RenderData.pCurrentMonData->m_shRGBA.discardOpaque = glGetUniformLocation(prog, "discardOpaque"); + m_RenderData.pCurrentMonData->m_shRGBA.discardAlpha = glGetUniformLocation(prog, "discardAlpha"); + m_RenderData.pCurrentMonData->m_shRGBA.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue"); + m_RenderData.pCurrentMonData->m_shRGBA.topLeft = glGetUniformLocation(prog, "topLeft"); + m_RenderData.pCurrentMonData->m_shRGBA.fullSize = glGetUniformLocation(prog, "fullSize"); + m_RenderData.pCurrentMonData->m_shRGBA.radius = glGetUniformLocation(prog, "radius"); + m_RenderData.pCurrentMonData->m_shRGBA.applyTint = glGetUniformLocation(prog, "applyTint"); + m_RenderData.pCurrentMonData->m_shRGBA.tint = glGetUniformLocation(prog, "tint"); prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBAPASSTHRU); m_RenderData.pCurrentMonData->m_shPASSTHRURGBA.program = prog; @@ -265,39 +263,37 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shGLITCH.time = glGetUniformLocation(prog, "time"); m_RenderData.pCurrentMonData->m_shGLITCH.fullSize = glGetUniformLocation(prog, "screenSize"); - prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBX); - m_RenderData.pCurrentMonData->m_shRGBX.program = prog; - m_RenderData.pCurrentMonData->m_shRGBX.tex = glGetUniformLocation(prog, "tex"); - m_RenderData.pCurrentMonData->m_shRGBX.proj = glGetUniformLocation(prog, "proj"); - m_RenderData.pCurrentMonData->m_shRGBX.alpha = glGetUniformLocation(prog, "alpha"); - m_RenderData.pCurrentMonData->m_shRGBX.texAttrib = glGetAttribLocation(prog, "texcoord"); - m_RenderData.pCurrentMonData->m_shRGBX.posAttrib = glGetAttribLocation(prog, "pos"); - m_RenderData.pCurrentMonData->m_shRGBX.discardOpaque = glGetUniformLocation(prog, "discardOpaque"); - m_RenderData.pCurrentMonData->m_shRGBX.discardAlpha = glGetUniformLocation(prog, "discardAlpha"); - m_RenderData.pCurrentMonData->m_shRGBX.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue"); - m_RenderData.pCurrentMonData->m_shRGBX.topLeft = glGetUniformLocation(prog, "topLeft"); - m_RenderData.pCurrentMonData->m_shRGBX.fullSize = glGetUniformLocation(prog, "fullSize"); - m_RenderData.pCurrentMonData->m_shRGBX.radius = glGetUniformLocation(prog, "radius"); - m_RenderData.pCurrentMonData->m_shRGBX.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample"); - m_RenderData.pCurrentMonData->m_shRGBX.applyTint = glGetUniformLocation(prog, "applyTint"); - m_RenderData.pCurrentMonData->m_shRGBX.tint = glGetUniformLocation(prog, "tint"); + prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBX); + m_RenderData.pCurrentMonData->m_shRGBX.program = prog; + m_RenderData.pCurrentMonData->m_shRGBX.tex = glGetUniformLocation(prog, "tex"); + m_RenderData.pCurrentMonData->m_shRGBX.proj = glGetUniformLocation(prog, "proj"); + m_RenderData.pCurrentMonData->m_shRGBX.alpha = glGetUniformLocation(prog, "alpha"); + m_RenderData.pCurrentMonData->m_shRGBX.texAttrib = glGetAttribLocation(prog, "texcoord"); + m_RenderData.pCurrentMonData->m_shRGBX.posAttrib = glGetAttribLocation(prog, "pos"); + m_RenderData.pCurrentMonData->m_shRGBX.discardOpaque = glGetUniformLocation(prog, "discardOpaque"); + m_RenderData.pCurrentMonData->m_shRGBX.discardAlpha = glGetUniformLocation(prog, "discardAlpha"); + m_RenderData.pCurrentMonData->m_shRGBX.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue"); + m_RenderData.pCurrentMonData->m_shRGBX.topLeft = glGetUniformLocation(prog, "topLeft"); + m_RenderData.pCurrentMonData->m_shRGBX.fullSize = glGetUniformLocation(prog, "fullSize"); + m_RenderData.pCurrentMonData->m_shRGBX.radius = glGetUniformLocation(prog, "radius"); + m_RenderData.pCurrentMonData->m_shRGBX.applyTint = glGetUniformLocation(prog, "applyTint"); + m_RenderData.pCurrentMonData->m_shRGBX.tint = glGetUniformLocation(prog, "tint"); - prog = createProgram(TEXVERTSRC, TEXFRAGSRCEXT); - m_RenderData.pCurrentMonData->m_shEXT.program = prog; - m_RenderData.pCurrentMonData->m_shEXT.tex = glGetUniformLocation(prog, "tex"); - m_RenderData.pCurrentMonData->m_shEXT.proj = glGetUniformLocation(prog, "proj"); - m_RenderData.pCurrentMonData->m_shEXT.alpha = glGetUniformLocation(prog, "alpha"); - m_RenderData.pCurrentMonData->m_shEXT.posAttrib = glGetAttribLocation(prog, "pos"); - m_RenderData.pCurrentMonData->m_shEXT.texAttrib = glGetAttribLocation(prog, "texcoord"); - m_RenderData.pCurrentMonData->m_shEXT.discardOpaque = glGetUniformLocation(prog, "discardOpaque"); - m_RenderData.pCurrentMonData->m_shEXT.discardAlpha = glGetUniformLocation(prog, "discardAlpha"); - m_RenderData.pCurrentMonData->m_shEXT.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue"); - m_RenderData.pCurrentMonData->m_shEXT.topLeft = glGetUniformLocation(prog, "topLeft"); - m_RenderData.pCurrentMonData->m_shEXT.fullSize = glGetUniformLocation(prog, "fullSize"); - m_RenderData.pCurrentMonData->m_shEXT.radius = glGetUniformLocation(prog, "radius"); - m_RenderData.pCurrentMonData->m_shEXT.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample"); - m_RenderData.pCurrentMonData->m_shEXT.applyTint = glGetUniformLocation(prog, "applyTint"); - m_RenderData.pCurrentMonData->m_shEXT.tint = glGetUniformLocation(prog, "tint"); + prog = createProgram(TEXVERTSRC, TEXFRAGSRCEXT); + m_RenderData.pCurrentMonData->m_shEXT.program = prog; + m_RenderData.pCurrentMonData->m_shEXT.tex = glGetUniformLocation(prog, "tex"); + m_RenderData.pCurrentMonData->m_shEXT.proj = glGetUniformLocation(prog, "proj"); + m_RenderData.pCurrentMonData->m_shEXT.alpha = glGetUniformLocation(prog, "alpha"); + m_RenderData.pCurrentMonData->m_shEXT.posAttrib = glGetAttribLocation(prog, "pos"); + m_RenderData.pCurrentMonData->m_shEXT.texAttrib = glGetAttribLocation(prog, "texcoord"); + m_RenderData.pCurrentMonData->m_shEXT.discardOpaque = glGetUniformLocation(prog, "discardOpaque"); + m_RenderData.pCurrentMonData->m_shEXT.discardAlpha = glGetUniformLocation(prog, "discardAlpha"); + m_RenderData.pCurrentMonData->m_shEXT.discardAlphaValue = glGetUniformLocation(prog, "discardAlphaValue"); + m_RenderData.pCurrentMonData->m_shEXT.topLeft = glGetUniformLocation(prog, "topLeft"); + m_RenderData.pCurrentMonData->m_shEXT.fullSize = glGetUniformLocation(prog, "fullSize"); + m_RenderData.pCurrentMonData->m_shEXT.radius = glGetUniformLocation(prog, "radius"); + m_RenderData.pCurrentMonData->m_shEXT.applyTint = glGetUniformLocation(prog, "applyTint"); + m_RenderData.pCurrentMonData->m_shEXT.tint = glGetUniformLocation(prog, "tint"); prog = createProgram(TEXVERTSRC, FRAGBLUR1); m_RenderData.pCurrentMonData->m_shBLUR1.program = prog; @@ -353,7 +349,6 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shBORDER1.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed = glGetUniformLocation(prog, "fullSizeUntransformed"); m_RenderData.pCurrentMonData->m_shBORDER1.radius = glGetUniformLocation(prog, "radius"); - m_RenderData.pCurrentMonData->m_shBORDER1.primitiveMultisample = glGetUniformLocation(prog, "primitiveMultisample"); m_RenderData.pCurrentMonData->m_shBORDER1.gradient = glGetUniformLocation(prog, "gradient"); m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength = glGetUniformLocation(prog, "gradientLength"); m_RenderData.pCurrentMonData->m_shBORDER1.angle = glGetUniformLocation(prog, "angle"); @@ -557,16 +552,13 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, CReg wlr_box_transform(&transformedBox, box, wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); - const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); - const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height); - - static auto* const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue; + const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); + const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height); // Rounded corners glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.topLeft, (float)TOPLEFT.x, (float)TOPLEFT.y); glUniform2f(m_RenderData.pCurrentMonData->m_shQUAD.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y); glUniform1f(m_RenderData.pCurrentMonData->m_shQUAD.radius, round); - glUniform1i(m_RenderData.pCurrentMonData->m_shQUAD.primitiveMultisample, (int)(*PMULTISAMPLEEDGES == 1 && round != 0)); glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); @@ -715,16 +707,14 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b wlr_box_transform(&transformedBox, &newBox, wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y); - const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); - const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height); - static auto* const PMULTISAMPLEEDGES = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue; + const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); + const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height); if (!usingFinalShader) { // Rounded corners glUniform2f(shader->topLeft, TOPLEFT.x, TOPLEFT.y); glUniform2f(shader->fullSize, FULLSIZE.x, FULLSIZE.y); glUniform1f(shader->radius, round); - glUniform1i(shader->primitiveMultisample, (int)(*PMULTISAMPLEEDGES == 1 && round != 0 && !noAA)); if (allowDim && m_pCurrentWindow && *PDIMINACTIVE) { glUniform1i(shader->applyTint, 1); @@ -1312,9 +1302,7 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad, if (m_RenderData.damage.empty() || (m_pCurrentWindow && m_pCurrentWindow->m_sAdditionalConfigData.forceNoBorder)) return; - static auto* const PMULTISAMPLE = &g_pConfigManager->getConfigValuePtr("decoration:multisample_edges")->intValue; - - wlr_box newBox = *box; + wlr_box newBox = *box; scaleBox(&newBox, m_RenderData.renderModif.scale); newBox.x += m_RenderData.renderModif.translate.x; newBox.y += m_RenderData.renderModif.translate.y; @@ -1372,7 +1360,6 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad, glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box->width, (float)box->height); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, scaledBorderSize); - glUniform1i(m_RenderData.pCurrentMonData->m_shBORDER1.primitiveMultisample, *PMULTISAMPLE); glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp index 01d35209..5945c157 100644 --- a/src/render/Shader.hpp +++ b/src/render/Shader.hpp @@ -23,7 +23,6 @@ class CShader { GLint fullSize = -1; GLint fullSizeUntransformed = -1; GLint radius = -1; - GLint primitiveMultisample = -1; GLint thick = -1; diff --git a/src/render/shaders/Border.hpp b/src/render/shaders/Border.hpp index 30227804..a4ab50ee 100644 --- a/src/render/shaders/Border.hpp +++ b/src/render/shaders/Border.hpp @@ -13,7 +13,6 @@ uniform vec2 fullSize; uniform vec2 fullSizeUntransformed; uniform float radius; uniform float thick; -uniform int primitiveMultisample; uniform vec4 gradient[10]; uniform int gradientLength; diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index 98cd8907..dac511c7 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -10,6 +10,7 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar pixCoord -= topLeft + fullSize * 0.5; pixCoord *= vec2(lessThan(pixCoord, vec2(0.0))) * -2.0 + 1.0; pixCoord -= fullSize * 0.5 - radius; + pixCoord += vec2(1.0, 1.0) / fullSize; // center the pix dont make it top-left if (pixCoord.x + pixCoord.y > radius) { @@ -18,20 +19,13 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar if (dist > radius) discard; - if (primitiveMultisample == 1 && dist > radius - 1.0) { - float distances = 0.0; - distances += float(length(pixCoord + vec2(0.25, 0.25)) < radius); - distances += float(length(pixCoord + vec2(0.75, 0.25)) < radius); - distances += float(length(pixCoord + vec2(0.25, 0.75)) < radius); - distances += float(length(pixCoord + vec2(0.75, 0.75)) < radius); + if (dist > radius - 1.0) { + float dist = length(pixCoord); - if (distances == 0.0) - discard; - - distances /= 4.0; + float normalized = 1.0 - clamp(smoothstep(0.0, 1.0, dist - radius + 0.5), 0.0, 1.0); )#" + - colorVarName + R"#( = )#" + colorVarName + R"#( * distances; + colorVarName + R"#( = )#" + colorVarName + R"#( * normalized; } } @@ -60,8 +54,6 @@ uniform vec2 topLeft; uniform vec2 fullSize; uniform float radius; -uniform int primitiveMultisample; - void main() { vec4 pixColor = v_color; @@ -102,8 +94,6 @@ uniform float discardAlphaValue; uniform int applyTint; uniform vec3 tint; -uniform int primitiveMultisample; - void main() { vec4 pixColor = texture2D(tex, v_texcoord); @@ -154,8 +144,6 @@ uniform int discardAlphaValue; uniform int applyTint; uniform vec3 tint; -uniform int primitiveMultisample; - void main() { if (discardOpaque == 1 && alpha == 1.0) @@ -274,8 +262,6 @@ uniform int discardAlphaValue; uniform int applyTint; uniform vec3 tint; -uniform int primitiveMultisample; - void main() { vec4 pixColor = texture2D(texture0, v_texcoord); From 86e8ed038f5b195cdf2548bc469f8f8bbc0caca8 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sat, 30 Sep 2023 02:09:08 +0100 Subject: [PATCH 021/513] includes: add missing log include to animatedvariable --- src/helpers/AnimatedVariable.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/helpers/AnimatedVariable.hpp b/src/helpers/AnimatedVariable.hpp index 57a772ae..059e892d 100644 --- a/src/helpers/AnimatedVariable.hpp +++ b/src/helpers/AnimatedVariable.hpp @@ -6,6 +6,7 @@ #include "Vector2D.hpp" #include "Color.hpp" #include "../macros.hpp" +#include "../debug/Log.hpp" enum ANIMATEDVARTYPE { From b8f8912db260c9fbe42afdba59f30f9e9546eef4 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sat, 30 Sep 2023 13:06:25 +0100 Subject: [PATCH 022/513] renderer: lock software cursors while tearing --- src/helpers/Monitor.hpp | 1 + src/render/Renderer.cpp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index f8b8554c..d0a86f3f 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -87,6 +87,7 @@ class CMonitor { bool nextRenderTorn = false; bool ignoreNextFlipEvent = false; bool renderingFromVblankEvent = false; + bool activelyTearing = false; // for the special workspace. 0 means not open. int specialWorkspaceID = 0; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index fefab56b..2e35efa8 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -884,6 +884,8 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } } + pMonitor->activelyTearing = shouldTear; + EMIT_HOOK_EVENT("preRender", pMonitor); timespec now; @@ -1023,6 +1025,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { TRACY_GPU_ZONE("RenderCursor"); bool lockSoftware = pMonitor == g_pCompositor->getMonitorFromCursor() && *PZOOMFACTOR != 1.f; + lockSoftware = lockSoftware || std::ranges::any_of(g_pCompositor->m_vMonitors, [](const auto& m) { return m->activelyTearing; }); if (lockSoftware) { wlr_output_lock_software_cursors(pMonitor->output, true); From a05076a7ee885a7d9ddf986684002d81890fb1e0 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sat, 30 Sep 2023 13:07:20 +0100 Subject: [PATCH 023/513] log: log wlr errors regardless of env --- src/Compositor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 05875f62..7fa45b07 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -133,6 +133,8 @@ void CCompositor::initServer() { const auto LOGWLR = getenv("HYPRLAND_LOG_WLR"); if (LOGWLR && std::string(LOGWLR) == "1") wlr_log_init(WLR_DEBUG, Debug::wlrLog); + else + wlr_log_init(WLR_ERROR, Debug::wlrLog); m_sWLRBackend = wlr_backend_autocreate(m_sWLDisplay, &m_sWLRSession); From 6a4643842dfc068e3759bab9ce2f9c55b845f2df Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sat, 30 Sep 2023 13:08:55 +0100 Subject: [PATCH 024/513] hyprctl: log activelyTearing for monitors --- src/debug/HyprCtl.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 8eced97d..56fc9fcf 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -63,14 +63,16 @@ std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) { "transform": {}, "focused": {}, "dpmsStatus": {}, - "vrr": {} + "vrr": {}, + "activelyTearing": {} }},)#", m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->output->description ? m->output->description : ""), (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace, escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName), m->specialWorkspaceID, escapeJSONStrings(getWorkspaceNameFromSpecialID(m->specialWorkspaceID)), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "true" : "false"), - (m->dpmsStatus ? "true" : "false"), (m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED ? "true" : "false")); + (m->dpmsStatus ? "true" : "false"), (m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED ? "true" : "false"), + m->activelyTearing ? "true" : "false"); } trimTrailingComma(result); @@ -85,13 +87,13 @@ std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) { std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\tspecial " "workspace: {} ({})\n\treserved: {} " "{} {} {}\n\tscale: {:.2f}\n\ttransform: " - "{}\n\tfocused: {}\n\tdpmsStatus: {}\n\tvrr: {}\n\n", + "{}\n\tfocused: {}\n\tdpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\n", m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, (m->output->description ? m->output->description : ""), (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName, m->specialWorkspaceID, getWorkspaceNameFromSpecialID(m->specialWorkspaceID), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, - (int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED)); + (int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED), m->activelyTearing); } } From 772c7d1d3cc7b3dd38450edf0ac1152419ef9eb1 Mon Sep 17 00:00:00 2001 From: Dickby Date: Sat, 30 Sep 2023 14:12:48 +0200 Subject: [PATCH 025/513] shaders: Remove redundant clamp of smoothsteps return value. (#3456) --- src/render/shaders/Border.hpp | 4 ++-- src/render/shaders/Textures.hpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/render/shaders/Border.hpp b/src/render/shaders/Border.hpp index a4ab50ee..f7b9d94d 100644 --- a/src/render/shaders/Border.hpp +++ b/src/render/shaders/Border.hpp @@ -71,11 +71,11 @@ void main() { if (dist < radius - h) { // lower - float normalized = clamp(smoothstep(0.0, 1.0, dist - radius + thick + 0.5), 0.0, 1.0); + float normalized = smoothstep(0.0, 1.0, dist - radius + thick + 0.5); additionalAlpha *= normalized; } else { // higher - float normalized = 1.0 - clamp(smoothstep(0.0, 1.0, dist - radius + 0.5), 0.0, 1.0); + float normalized = 1.0 - smoothstep(0.0, 1.0, dist - radius + 0.5); additionalAlpha *= normalized; } diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index dac511c7..109840ca 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -22,7 +22,7 @@ inline static constexpr auto ROUNDED_SHADER_FUNC = [](const std::string colorVar if (dist > radius - 1.0) { float dist = length(pixCoord); - float normalized = 1.0 - clamp(smoothstep(0.0, 1.0, dist - radius + 0.5), 0.0, 1.0); + float normalized = 1.0 - smoothstep(0.0, 1.0, dist - radius + 0.5); )#" + colorVarName + R"#( = )#" + colorVarName + R"#( * normalized; @@ -100,7 +100,7 @@ void main() { if (discardOpaque == 1 && pixColor[3] * alpha == 1.0) discard; - + if (discardAlpha == 1 && pixColor[3] <= discardAlphaValue) discard; @@ -349,4 +349,4 @@ void main() { gl_FragColor = pixColor; } -)#"; \ No newline at end of file +)#"; From e2b72b2975782719759b989853578db95671b069 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sat, 30 Sep 2023 16:55:41 +0100 Subject: [PATCH 026/513] renderer: avoid spamming software cursor locks --- src/render/Renderer.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 2e35efa8..ea6a246a 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -884,7 +884,14 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } } - pMonitor->activelyTearing = shouldTear; + if (pMonitor->activelyTearing != shouldTear) { + // change of state + pMonitor->activelyTearing = shouldTear; + + for (auto& m : g_pCompositor->m_vMonitors) { + wlr_output_lock_software_cursors(m->output, pMonitor->activelyTearing); + } + } EMIT_HOOK_EVENT("preRender", pMonitor); @@ -1025,7 +1032,6 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { TRACY_GPU_ZONE("RenderCursor"); bool lockSoftware = pMonitor == g_pCompositor->getMonitorFromCursor() && *PZOOMFACTOR != 1.f; - lockSoftware = lockSoftware || std::ranges::any_of(g_pCompositor->m_vMonitors, [](const auto& m) { return m->activelyTearing; }); if (lockSoftware) { wlr_output_lock_software_cursors(pMonitor->output, true); From a2a29a60e5301df2cadf58c1bb18495d02710547 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sat, 30 Sep 2023 17:07:50 +0100 Subject: [PATCH 027/513] tearing: cleanup vars and avoid rendering before drm is ready --- src/debug/HyprCtl.cpp | 4 ++-- src/events/Monitors.cpp | 17 +++++++++-------- src/helpers/Monitor.cpp | 2 +- src/helpers/Monitor.hpp | 16 ++++++++++------ src/helpers/SubsurfaceTree.cpp | 11 ++++++++--- src/render/Renderer.cpp | 20 +++++++------------- 6 files changed, 37 insertions(+), 33 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 56fc9fcf..a86ac33e 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -72,7 +72,7 @@ std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) { m->specialWorkspaceID, escapeJSONStrings(getWorkspaceNameFromSpecialID(m->specialWorkspaceID)), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "true" : "false"), (m->dpmsStatus ? "true" : "false"), (m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED ? "true" : "false"), - m->activelyTearing ? "true" : "false"); + m->tearingState.activelyTearing ? "true" : "false"); } trimTrailingComma(result); @@ -93,7 +93,7 @@ std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) { (m->output->serial ? m->output->serial : ""), m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName, m->specialWorkspaceID, getWorkspaceNameFromSpecialID(m->specialWorkspaceID), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, - (int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED), m->activelyTearing); + (int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED), m->tearingState.activelyTearing); } } diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 24e7cc26..0b90ba1e 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -149,19 +149,22 @@ void Events::listener_monitorFrame(void* owner, void* data) { if (!PMONITOR->m_bEnabled) return; - if (PMONITOR->ignoreNextFlipEvent) { - PMONITOR->ignoreNextFlipEvent = false; - return; - } + PMONITOR->tearingState.busy = false; - PMONITOR->renderingFromVblankEvent = true; + if (PMONITOR->tearingState.activelyTearing) { + + if (!PMONITOR->tearingState.frameScheduledWhileBusy) + return; // we did not schedule a frame yet to be displayed, but we are tearing. Why render? + + PMONITOR->tearingState.nextRenderTorn = true; + } static auto* const PENABLERAT = &g_pConfigManager->getConfigValuePtr("misc:render_ahead_of_time")->intValue; static auto* const PRATSAFE = &g_pConfigManager->getConfigValuePtr("misc:render_ahead_safezone")->intValue; PMONITOR->lastPresentationTimer.reset(); - if (*PENABLERAT) { + if (*PENABLERAT && !PMONITOR->tearingState.nextRenderTorn) { if (!PMONITOR->RATScheduled) { // render g_pHyprRenderer->renderMonitor(PMONITOR); @@ -188,8 +191,6 @@ void Events::listener_monitorFrame(void* owner, void* data) { } else { g_pHyprRenderer->renderMonitor(PMONITOR); } - - PMONITOR->renderingFromVblankEvent = false; } void Events::listener_monitorDestroy(void* owner, void* data) { diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 0d0b2a64..25a17189 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -40,7 +40,7 @@ void CMonitor::onConnect(bool noRule) { hyprListener_monitorCommit.initCallback(&output->events.commit, &Events::listener_monitorCommit, this); hyprListener_monitorBind.initCallback(&output->events.bind, &Events::listener_monitorBind, this); - canTear = wlr_backend_is_drm(output->backend); // tearing only works on drm + tearingState.canTear = wlr_backend_is_drm(output->backend); // tearing only works on drm if (m_bEnabled) { wlr_output_enable(output, 1); diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index d0a86f3f..71c84273 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -82,12 +82,16 @@ class CMonitor { CRegion lastFrameDamage; // stores last frame damage // for tearing - CWindow* solitaryClient = nullptr; - bool canTear = false; - bool nextRenderTorn = false; - bool ignoreNextFlipEvent = false; - bool renderingFromVblankEvent = false; - bool activelyTearing = false; + CWindow* solitaryClient = nullptr; + + struct { + bool canTear = false; + bool nextRenderTorn = false; + bool activelyTearing = false; + + bool busy = false; + bool frameScheduledWhileBusy = false; + } tearingState; // for the special workspace. 0 means not open. int specialWorkspaceID = 0; diff --git a/src/helpers/SubsurfaceTree.cpp b/src/helpers/SubsurfaceTree.cpp index 0efa4c49..76a392e8 100644 --- a/src/helpers/SubsurfaceTree.cpp +++ b/src/helpers/SubsurfaceTree.cpp @@ -249,14 +249,19 @@ void Events::listener_commitSubsurface(void* owner, void* data) { if (pNode->pWindowOwner) { // tearing: if solitary, redraw it. This still might be a single surface window const auto PMONITOR = g_pCompositor->getMonitorFromID(pNode->pWindowOwner->m_iMonitorID); - if (PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->canBeTorn() && PMONITOR->canTear) { + if (PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->canBeTorn() && PMONITOR->tearingState.canTear) { CRegion damageBox; wlr_surface_get_effective_damage(pNode->pSurface->wlr(), damageBox.pixman()); if (!damageBox.empty()) { - PMONITOR->nextRenderTorn = true; - g_pHyprRenderer->renderMonitor(PMONITOR); + + if (PMONITOR->tearingState.busy) { + PMONITOR->tearingState.frameScheduledWhileBusy = true; + } else { + PMONITOR->tearingState.nextRenderTorn = true; + g_pHyprRenderer->renderMonitor(PMONITOR); + } } } } diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index ea6a246a..12b745ff 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -846,10 +846,9 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { // tearing and DS first bool shouldTear = false; - bool canTear = *PTEARINGENABLED && g_pHyprOpenGL->m_RenderData.mouseZoomFactor == 1.0; recheckSolitaryForMonitor(pMonitor); - if (pMonitor->nextRenderTorn) { - pMonitor->nextRenderTorn = false; + if (pMonitor->tearingState.nextRenderTorn) { + pMonitor->tearingState.nextRenderTorn = false; if (!*PTEARINGENABLED) { Debug::log(WARN, "Tearing commit requested but the master switch general:allow_tearing is off, ignoring"); @@ -861,18 +860,13 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { return; } - if (!pMonitor->canTear) { + if (!pMonitor->tearingState.canTear) { Debug::log(WARN, "Tearing commit requested but monitor doesn't support it, ignoring"); return; } if (pMonitor->solitaryClient) shouldTear = true; - } else { - // if this is a non-tearing commit, and we are in a state where we should tear - // then this is a vblank commit that we should ignore - if (canTear && pMonitor->solitaryClient && pMonitor->canTear && pMonitor->solitaryClient->canBeTorn() && pMonitor->renderingFromVblankEvent) - return; } if (!*PNODIRECTSCANOUT && !shouldTear) { @@ -884,12 +878,12 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } } - if (pMonitor->activelyTearing != shouldTear) { + if (pMonitor->tearingState.activelyTearing != shouldTear) { // change of state - pMonitor->activelyTearing = shouldTear; + pMonitor->tearingState.activelyTearing = shouldTear; for (auto& m : g_pCompositor->m_vMonitors) { - wlr_output_lock_software_cursors(m->output, pMonitor->activelyTearing); + wlr_output_lock_software_cursors(m->output, pMonitor->tearingState.activelyTearing); } } @@ -1090,7 +1084,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } if (shouldTear) - pMonitor->ignoreNextFlipEvent = true; + pMonitor->tearingState.busy = true; wlr_damage_ring_rotate(&pMonitor->damage); From 161fee1d8236978eca44efdbede8015763533482 Mon Sep 17 00:00:00 2001 From: memchr <118117622+memchr@users.noreply.github.com> Date: Sun, 1 Oct 2023 11:26:10 +0000 Subject: [PATCH 028/513] internal: include missing header (#3464) --- src/helpers/WLListener.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/helpers/WLListener.cpp b/src/helpers/WLListener.cpp index cace665d..402c999c 100644 --- a/src/helpers/WLListener.cpp +++ b/src/helpers/WLListener.cpp @@ -2,6 +2,7 @@ #include "MiscFunctions.hpp" #include #include "../debug/Log.hpp" +#include "Watchdog.hpp" void handleWrapped(wl_listener* listener, void* data) { CHyprWLListener::SWrapper* pWrap = wl_container_of(listener, pWrap, m_sListener); @@ -56,4 +57,4 @@ void CHyprWLListener::initCallback(wl_signal* pSignal, std::function Date: Sun, 1 Oct 2023 14:09:46 +0100 Subject: [PATCH 029/513] makefile: make binaries 755 instead of 711 fixes #3466 --- Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index b980d561..07187d73 100644 --- a/Makefile +++ b/Makefile @@ -3,22 +3,22 @@ PREFIX = /usr/local legacyrenderer: cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` - chmod 711 ./build/Hyprland + chmod 755 ./build/Hyprland legacyrendererdebug: cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` - chmod 711 ./build/Hyprland + chmod 755 ./build/Hyprland release: cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` - chmod 711 ./build/Hyprland + chmod 755 ./build/Hyprland debug: cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -S . -B ./build -G Ninja cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` - chmod 711 ./build/Hyprland + chmod 755 ./build/Hyprland clear: rm -rf build @@ -43,14 +43,14 @@ install: chmod -R 777 subprojects/wlroots $(MAKE) release $(MAKE) -C hyprctl all - chmod 711 ./hyprctl/hyprctl + chmod 755 ./hyprctl/hyprctl mkdir -p ${PREFIX}/share/wayland-sessions mkdir -p ${PREFIX}/bin cp -f ./build/Hyprland ${PREFIX}/bin cp -f ./hyprctl/hyprctl ${PREFIX}/bin - chmod 711 ${PREFIX}/bin/Hyprland - chmod 711 ${PREFIX}/bin/hyprctl + chmod 755 ${PREFIX}/bin/Hyprland + chmod 755 ${PREFIX}/bin/hyprctl if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi mkdir -p ${PREFIX}/share/hyprland cp ./assets/wall_* ${PREFIX}/share/hyprland From 763bb2d3bc81dd8d73d464d8ede1a3c696dd0555 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 2 Oct 2023 10:50:33 +0100 Subject: [PATCH 030/513] renderer: remove old debug log --- src/render/Renderer.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 12b745ff..6046a5b6 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2054,9 +2054,6 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { wlr_xdg_surface_for_each_popup_surface(PCANDIDATE->m_uSurface.xdg, countSubsurfacesIter, &surfaceCount); } - if (surfaceCount != 1) - Debug::log(LOG, "fuf: >1 surf"); - // found one! pMonitor->solitaryClient = PCANDIDATE; } From 778bdf730ff957521cc114d170bc82fc44b8be22 Mon Sep 17 00:00:00 2001 From: gnusenpai Date: Mon, 2 Oct 2023 09:51:15 +0000 Subject: [PATCH 031/513] internal: Add GTK portal as fallback (#3469) needed for XDP 1.17+ since the fallback to the GTK portal was removed --- assets/hyprland-portals.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/hyprland-portals.conf b/assets/hyprland-portals.conf index 2ec1f0de..da8b5db0 100644 --- a/assets/hyprland-portals.conf +++ b/assets/hyprland-portals.conf @@ -1,2 +1,2 @@ [preferred] -default=hyprland \ No newline at end of file +default=hyprland;gtk \ No newline at end of file From fc1d7acd9a7e02fabf8091742bd6c613aa764f05 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 2 Oct 2023 14:02:15 +0100 Subject: [PATCH 032/513] renderer: fix missing check for surfaceCount in rechecking solitary closes #3470 --- src/render/Renderer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 6046a5b6..f0d00592 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2054,6 +2054,9 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { wlr_xdg_surface_for_each_popup_surface(PCANDIDATE->m_uSurface.xdg, countSubsurfacesIter, &surfaceCount); } + if (surfaceCount > 1) + return; + // found one! pMonitor->solitaryClient = PCANDIDATE; } From 5ffb1032e171b88dc45e0169159e449989a0fc58 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 2 Oct 2023 14:09:23 +0100 Subject: [PATCH 033/513] events: don't focus new window if spawned behind fullscreen fixes #3473 --- src/events/Windows.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index f726b224..88ccab22 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -467,6 +467,8 @@ void Events::listener_mapWindow(void* owner, void* data) { const auto PLSFROMFOCUS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus); if (PLSFROMFOCUS && PLSFROMFOCUS->layerSurface->current.keyboard_interactive) PWINDOW->m_bNoInitialFocus = true; + if (PWORKSPACE->m_bHasFullscreenWindow && !requestsFullscreen) + PWINDOW->m_bNoInitialFocus = true; if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus && (PWINDOW->m_iX11Type != 2 || (PWINDOW->m_bIsX11 && wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))) && !workspaceSilent && From 50fecf084d06f8b982194fdc9cf53a40741d8453 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 2 Oct 2023 16:22:39 +0100 Subject: [PATCH 034/513] events: set new window alpha to 0 if it's tiled behind fullscreen fixes #3474 --- src/events/Windows.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 88ccab22..2ea4e46c 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -633,6 +633,9 @@ void Events::listener_mapWindow(void* owner, void* data) { // recalc the values for this window g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW); + // avoid this window being visible + if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFullscreen && !PWINDOW->m_bIsFloating) + PWINDOW->m_fAlpha.setValueAndWarp(0.f); g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale); } From b814ba98a7c74e29afe4e5e543ee6d0283a67d67 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 2 Oct 2023 16:27:32 +0100 Subject: [PATCH 035/513] misc: add misc:new_window_takes_over_fullscreen referenced in #3474 --- src/config/ConfigManager.cpp | 69 ++++++++++++++++++------------------ src/events/Windows.cpp | 9 +++-- 2 files changed, 42 insertions(+), 36 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index cffd2587..d639df0c 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -89,40 +89,41 @@ void CConfigManager::setDefaultVars() { configValues["general:layout"].strValue = "dwindle"; configValues["general:allow_tearing"].intValue = 0; - configValues["misc:disable_hyprland_logo"].intValue = 0; - configValues["misc:disable_splash_rendering"].intValue = 0; - configValues["misc:disable_hypr_chan"].intValue = 0; - configValues["misc:force_hypr_chan"].intValue = 0; - configValues["misc:vfr"].intValue = 1; - configValues["misc:vrr"].intValue = 0; - configValues["misc:mouse_move_enables_dpms"].intValue = 0; - configValues["misc:key_press_enables_dpms"].intValue = 0; - configValues["misc:always_follow_on_dnd"].intValue = 1; - configValues["misc:layers_hog_keyboard_focus"].intValue = 1; - configValues["misc:animate_manual_resizes"].intValue = 0; - configValues["misc:animate_mouse_windowdragging"].intValue = 0; - configValues["misc:disable_autoreload"].intValue = 0; - configValues["misc:enable_swallow"].intValue = 0; - configValues["misc:swallow_regex"].strValue = STRVAL_EMPTY; - configValues["misc:swallow_exception_regex"].strValue = STRVAL_EMPTY; - configValues["misc:focus_on_activate"].intValue = 0; - configValues["misc:no_direct_scanout"].intValue = 1; - configValues["misc:hide_cursor_on_touch"].intValue = 1; - configValues["misc:mouse_move_focuses_monitor"].intValue = 1; - configValues["misc:render_ahead_of_time"].intValue = 0; - configValues["misc:render_ahead_safezone"].intValue = 1; - configValues["misc:cursor_zoom_factor"].floatValue = 1.f; - configValues["misc:cursor_zoom_rigid"].intValue = 0; - configValues["misc:allow_session_lock_restore"].intValue = 0; - configValues["misc:groupbar_scrolling"].intValue = 1; - configValues["misc:group_insert_after_current"].intValue = 1; - configValues["misc:group_focus_removed_window"].intValue = 1; - configValues["misc:render_titles_in_groupbar"].intValue = 1; - configValues["misc:groupbar_titles_font_size"].intValue = 8; - configValues["misc:groupbar_gradients"].intValue = 1; - configValues["misc:close_special_on_empty"].intValue = 1; - configValues["misc:groupbar_text_color"].intValue = 0xffffffff; - configValues["misc:background_color"].intValue = 0xff111111; + configValues["misc:disable_hyprland_logo"].intValue = 0; + configValues["misc:disable_splash_rendering"].intValue = 0; + configValues["misc:disable_hypr_chan"].intValue = 0; + configValues["misc:force_hypr_chan"].intValue = 0; + configValues["misc:vfr"].intValue = 1; + configValues["misc:vrr"].intValue = 0; + configValues["misc:mouse_move_enables_dpms"].intValue = 0; + configValues["misc:key_press_enables_dpms"].intValue = 0; + configValues["misc:always_follow_on_dnd"].intValue = 1; + configValues["misc:layers_hog_keyboard_focus"].intValue = 1; + configValues["misc:animate_manual_resizes"].intValue = 0; + configValues["misc:animate_mouse_windowdragging"].intValue = 0; + configValues["misc:disable_autoreload"].intValue = 0; + configValues["misc:enable_swallow"].intValue = 0; + configValues["misc:swallow_regex"].strValue = STRVAL_EMPTY; + configValues["misc:swallow_exception_regex"].strValue = STRVAL_EMPTY; + configValues["misc:focus_on_activate"].intValue = 0; + configValues["misc:no_direct_scanout"].intValue = 1; + configValues["misc:hide_cursor_on_touch"].intValue = 1; + configValues["misc:mouse_move_focuses_monitor"].intValue = 1; + configValues["misc:render_ahead_of_time"].intValue = 0; + configValues["misc:render_ahead_safezone"].intValue = 1; + configValues["misc:cursor_zoom_factor"].floatValue = 1.f; + configValues["misc:cursor_zoom_rigid"].intValue = 0; + configValues["misc:allow_session_lock_restore"].intValue = 0; + configValues["misc:groupbar_scrolling"].intValue = 1; + configValues["misc:group_insert_after_current"].intValue = 1; + configValues["misc:group_focus_removed_window"].intValue = 1; + configValues["misc:render_titles_in_groupbar"].intValue = 1; + configValues["misc:groupbar_titles_font_size"].intValue = 8; + configValues["misc:groupbar_gradients"].intValue = 1; + configValues["misc:close_special_on_empty"].intValue = 1; + configValues["misc:groupbar_text_color"].intValue = 0xffffffff; + configValues["misc:background_color"].intValue = 0xff111111; + configValues["misc:new_window_takes_over_fullscreen"].intValue = 0; configValues["debug:int"].intValue = 0; configValues["debug:log_damage"].intValue = 0; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 2ea4e46c..b870f01d 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -46,6 +46,7 @@ void Events::listener_mapWindow(void* owner, void* data) { static auto* const PSWALLOW = &g_pConfigManager->getConfigValuePtr("misc:enable_swallow")->intValue; static auto* const PSWALLOWREGEX = &g_pConfigManager->getConfigValuePtr("misc:swallow_regex")->strValue; static auto* const PSWALLOWEXREGEX = &g_pConfigManager->getConfigValuePtr("misc:swallow_exception_regex")->strValue; + static auto* const PNEWTAKESOVERFS = &g_pConfigManager->getConfigValuePtr("misc:new_window_takes_over_fullscreen")->intValue; auto PMONITOR = g_pCompositor->m_pLastMonitor; const auto PWORKSPACE = @@ -467,8 +468,12 @@ void Events::listener_mapWindow(void* owner, void* data) { const auto PLSFROMFOCUS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus); if (PLSFROMFOCUS && PLSFROMFOCUS->layerSurface->current.keyboard_interactive) PWINDOW->m_bNoInitialFocus = true; - if (PWORKSPACE->m_bHasFullscreenWindow && !requestsFullscreen) - PWINDOW->m_bNoInitialFocus = true; + if (PWORKSPACE->m_bHasFullscreenWindow && !requestsFullscreen) { + if (*PNEWTAKESOVERFS == 0) + PWINDOW->m_bNoInitialFocus = true; + else + requestsFullscreen = true; + } if (!PWINDOW->m_bNoFocus && !PWINDOW->m_bNoInitialFocus && (PWINDOW->m_iX11Type != 2 || (PWINDOW->m_bIsX11 && wlr_xwayland_or_surface_wants_focus(PWINDOW->m_uSurface.xwayland))) && !workspaceSilent && From fcab2a435899f3848bc814ac4784d29e3169ea0b Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 2 Oct 2023 16:47:54 +0100 Subject: [PATCH 036/513] deps: update wlroots --- subprojects/wlroots | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/wlroots b/subprojects/wlroots index c2aa7fd9..5ef42e8e 160000 --- a/subprojects/wlroots +++ b/subprojects/wlroots @@ -1 +1 @@ -Subproject commit c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e +Subproject commit 5ef42e8e8adece098848fac53c721b6eb3818fc2 From b784931e678f907b1f1e41d04485fefd8a1faaf8 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 2 Oct 2023 15:48:58 +0000 Subject: [PATCH 037/513] [gha] Nix: update wlroots --- flake.lock | 8 ++++---- flake.nix | 2 +- subprojects/wlroots.wrap | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 524ca010..4c6f209b 100644 --- a/flake.lock +++ b/flake.lock @@ -67,18 +67,18 @@ "flake": false, "locked": { "host": "gitlab.freedesktop.org", - "lastModified": 1695919988, - "narHash": "sha256-4RBgIZHaVqH0m1POnfzYRzwCWxifIKH4xQ0kCn2LGkA=", + "lastModified": 1696255886, + "narHash": "sha256-0KZfiqqREousitBgG1mkzKmmNX4tjOIWdbBm6MvRCjQ=", "owner": "wlroots", "repo": "wlroots", - "rev": "c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e", + "rev": "5ef42e8e8adece098848fac53c721b6eb3818fc2", "type": "gitlab" }, "original": { "host": "gitlab.freedesktop.org", "owner": "wlroots", "repo": "wlroots", - "rev": "c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e", + "rev": "5ef42e8e8adece098848fac53c721b6eb3818fc2", "type": "gitlab" } }, diff --git a/flake.nix b/flake.nix index d2eb35c5..2491001e 100644 --- a/flake.nix +++ b/flake.nix @@ -12,7 +12,7 @@ host = "gitlab.freedesktop.org"; owner = "wlroots"; repo = "wlroots"; - rev = "c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e"; + rev = "5ef42e8e8adece098848fac53c721b6eb3818fc2"; flake = false; }; diff --git a/subprojects/wlroots.wrap b/subprojects/wlroots.wrap index 04427ba6..ab7bf743 100644 --- a/subprojects/wlroots.wrap +++ b/subprojects/wlroots.wrap @@ -1,7 +1,7 @@ [wrap-git] directory = wlroots url = https://gitlab.freedesktop.org/wlroots/wlroots.git -revision = c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e +revision = 5ef42e8e8adece098848fac53c721b6eb3818fc2 depth = 1 diff_files = wlroots-meson-build.patch From d61e4f9ad75d51f15eac6bced13439899d66a950 Mon Sep 17 00:00:00 2001 From: Jeremy Huang <66577496+thejch@users.noreply.github.com> Date: Tue, 3 Oct 2023 14:16:57 -0700 Subject: [PATCH 038/513] master: add option to drag and drop windows at cursor position (#3465) * add option to drag and drop a window at cursor position * use getWindowIdealBoundingBoxIgnoreReserved --- src/config/ConfigManager.cpp | 1 + src/layout/MasterLayout.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index d639df0c..42611be3 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -188,6 +188,7 @@ void CConfigManager::setDefaultVars() { configValues["master:inherit_fullscreen"].intValue = 1; configValues["master:allow_small_split"].intValue = 0; configValues["master:smart_resizing"].intValue = 1; + configValues["master:drop_at_cursor"].intValue = 1; configValues["animations:enabled"].intValue = 1; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 624ded2a..6fa168c4 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -132,6 +132,35 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc pWindow->applyGroupRules(); + static auto* const PDROPATCURSOR = &g_pConfigManager->getConfigValuePtr("master:drop_at_cursor")->intValue; + const auto PWORKSPACEDATA = getMasterWorkspaceData(pWindow->m_iWorkspaceID); + eOrientation orientation = PWORKSPACEDATA->orientation; + const auto NODEIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *PNODE); + if (*PDROPATCURSOR && g_pInputManager->dragMode == MBIND_MOVE) { + // if dragging window to move, drop it at the cursor position instead of bottom/top of stack + for (auto it = m_lMasterNodesData.begin(); it != m_lMasterNodesData.end(); ++it) { + const wlr_box box = it->pWindow->getWindowIdealBoundingBoxIgnoreReserved(); + if (wlr_box_contains_point(&box, MOUSECOORDS.x, MOUSECOORDS.y)) { // TODO: Deny when not using mouse + switch (orientation) { + case ORIENTATION_LEFT: + case ORIENTATION_RIGHT: + if (MOUSECOORDS.y > it->pWindow->middle().y) + ++it; + break; + case ORIENTATION_TOP: + case ORIENTATION_BOTTOM: + if (MOUSECOORDS.x > it->pWindow->middle().x) + ++it; + break; + case ORIENTATION_CENTER: break; + default: UNREACHABLE(); + } + m_lMasterNodesData.splice(it, m_lMasterNodesData, NODEIT); + break; + } + } + } + if (*PNEWISMASTER || WINDOWSONWORKSPACE == 1 || (!pWindow->m_bFirstMap && OPENINGON->isMaster)) { for (auto& nd : m_lMasterNodesData) { if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) { From 2901bb0d2f69f90bc4e2f8fabbc78a0df8130523 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Wed, 4 Oct 2023 09:44:03 +0100 Subject: [PATCH 039/513] renderer: add further conditions to solitary recheck --- src/render/Renderer.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index f0d00592..0d5d6d1d 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2045,6 +2045,14 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { return; } + for (auto& w : g_pCompositor->m_vWindows) { + if (w->m_iWorkspaceID == PCANDIDATE->m_iWorkspaceID && w->m_bIsFloating && w->m_bCreatedOverFullscreen && !w->isHidden()) + return; + } + + if (pMonitor->specialWorkspaceID != 0) + return; + // check if it did not open any subsurfaces or shit int surfaceCount = 0; if (PCANDIDATE->m_bIsX11) { From f803be3d3150288710a924e3ca56ade9a1893f0f Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Wed, 4 Oct 2023 12:57:37 +0100 Subject: [PATCH 040/513] input: fixup frame schedule conditions on mouse move --- src/managers/input/InputManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index caed742e..fe66b8ba 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -115,7 +115,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (*PZOOMFACTOR != 1.f) g_pHyprRenderer->damageMonitor(PMONITOR); - if (!PMONITOR->solitaryClient) // if there is a solitary client we can't schedule a frame here, this will completely fuck up drm + if (!PMONITOR->solitaryClient && g_pHyprRenderer->shouldRenderCursor()) g_pCompositor->scheduleFrameForMonitor(PMONITOR); CWindow* forcedFocus = m_pForcedFocus; From f8c18ff7977cf034572cbabe161381465bc2b1ae Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Wed, 4 Oct 2023 13:30:13 +0100 Subject: [PATCH 041/513] renderer: fixup solitary conditions --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 0d5d6d1d..bee1605d 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2046,7 +2046,7 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { } for (auto& w : g_pCompositor->m_vWindows) { - if (w->m_iWorkspaceID == PCANDIDATE->m_iWorkspaceID && w->m_bIsFloating && w->m_bCreatedOverFullscreen && !w->isHidden()) + if (w->m_iWorkspaceID == PCANDIDATE->m_iWorkspaceID && w->m_bIsFloating && w->m_bCreatedOverFullscreen && !w->isHidden() && w->m_bIsMapped && w.get() != PCANDIDATE) return; } From 4531717f3ee58f6093f62e5afb21da6599b5a813 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Wed, 4 Oct 2023 13:39:40 +0100 Subject: [PATCH 042/513] renderer: considerable fixes to repaint logic --- src/events/Monitors.cpp | 3 ++- src/helpers/SubsurfaceTree.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 0b90ba1e..82577dae 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -156,7 +156,8 @@ void Events::listener_monitorFrame(void* owner, void* data) { if (!PMONITOR->tearingState.frameScheduledWhileBusy) return; // we did not schedule a frame yet to be displayed, but we are tearing. Why render? - PMONITOR->tearingState.nextRenderTorn = true; + PMONITOR->tearingState.nextRenderTorn = true; + PMONITOR->tearingState.frameScheduledWhileBusy = false; } static auto* const PENABLERAT = &g_pConfigManager->getConfigValuePtr("misc:render_ahead_of_time")->intValue; diff --git a/src/helpers/SubsurfaceTree.cpp b/src/helpers/SubsurfaceTree.cpp index 76a392e8..b0ed0bfa 100644 --- a/src/helpers/SubsurfaceTree.cpp +++ b/src/helpers/SubsurfaceTree.cpp @@ -249,7 +249,8 @@ void Events::listener_commitSubsurface(void* owner, void* data) { if (pNode->pWindowOwner) { // tearing: if solitary, redraw it. This still might be a single surface window const auto PMONITOR = g_pCompositor->getMonitorFromID(pNode->pWindowOwner->m_iMonitorID); - if (PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->canBeTorn() && PMONITOR->tearingState.canTear) { + if (PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->canBeTorn() && PMONITOR->tearingState.canTear && + pNode->pSurface->wlr()->current.committed & WLR_SURFACE_STATE_BUFFER) { CRegion damageBox; wlr_surface_get_effective_damage(pNode->pSurface->wlr(), damageBox.pixman()); From 230356012be03412db78a9e85c711ec878fd0a69 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Wed, 4 Oct 2023 13:48:44 +0100 Subject: [PATCH 043/513] renderer: extract solitary check into frame handler --- src/events/Monitors.cpp | 4 +++- src/render/Renderer.cpp | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 82577dae..8619ade3 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -149,9 +149,11 @@ void Events::listener_monitorFrame(void* owner, void* data) { if (!PMONITOR->m_bEnabled) return; + g_pHyprRenderer->recheckSolitaryForMonitor(PMONITOR); + PMONITOR->tearingState.busy = false; - if (PMONITOR->tearingState.activelyTearing) { + if (PMONITOR->tearingState.activelyTearing && PMONITOR->solitaryClient /* can be invalidated by a recheck */) { if (!PMONITOR->tearingState.frameScheduledWhileBusy) return; // we did not schedule a frame yet to be displayed, but we are tearing. Why render? diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index bee1605d..a685f735 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -846,7 +846,6 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { // tearing and DS first bool shouldTear = false; - recheckSolitaryForMonitor(pMonitor); if (pMonitor->tearingState.nextRenderTorn) { pMonitor->tearingState.nextRenderTorn = false; From 322c5cc4b97855165bd14dd1b072ec5cdf53d57b Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 4 Oct 2023 15:00:24 +0100 Subject: [PATCH 044/513] layout: add new_window_takes_over_fullscreen mode 2 fixes #3486 --- src/events/Windows.cpp | 2 ++ subprojects/wlroots | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index b870f01d..54ffb37e 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -471,6 +471,8 @@ void Events::listener_mapWindow(void* owner, void* data) { if (PWORKSPACE->m_bHasFullscreenWindow && !requestsFullscreen) { if (*PNEWTAKESOVERFS == 0) PWINDOW->m_bNoInitialFocus = true; + else if (*PNEWTAKESOVERFS == 2) + g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), false, FULLSCREEN_INVALID); else requestsFullscreen = true; } diff --git a/subprojects/wlroots b/subprojects/wlroots index 5ef42e8e..c2aa7fd9 160000 --- a/subprojects/wlroots +++ b/subprojects/wlroots @@ -1 +1 @@ -Subproject commit 5ef42e8e8adece098848fac53c721b6eb3818fc2 +Subproject commit c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e From e689b1ba11d7adadfda6f4e93d3e5e322c914bee Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 4 Oct 2023 14:01:11 +0000 Subject: [PATCH 045/513] [gha] Nix: update wlroots --- flake.lock | 8 ++++---- flake.nix | 2 +- subprojects/wlroots.wrap | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 4c6f209b..524ca010 100644 --- a/flake.lock +++ b/flake.lock @@ -67,18 +67,18 @@ "flake": false, "locked": { "host": "gitlab.freedesktop.org", - "lastModified": 1696255886, - "narHash": "sha256-0KZfiqqREousitBgG1mkzKmmNX4tjOIWdbBm6MvRCjQ=", + "lastModified": 1695919988, + "narHash": "sha256-4RBgIZHaVqH0m1POnfzYRzwCWxifIKH4xQ0kCn2LGkA=", "owner": "wlroots", "repo": "wlroots", - "rev": "5ef42e8e8adece098848fac53c721b6eb3818fc2", + "rev": "c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e", "type": "gitlab" }, "original": { "host": "gitlab.freedesktop.org", "owner": "wlroots", "repo": "wlroots", - "rev": "5ef42e8e8adece098848fac53c721b6eb3818fc2", + "rev": "c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e", "type": "gitlab" } }, diff --git a/flake.nix b/flake.nix index 2491001e..d2eb35c5 100644 --- a/flake.nix +++ b/flake.nix @@ -12,7 +12,7 @@ host = "gitlab.freedesktop.org"; owner = "wlroots"; repo = "wlroots"; - rev = "5ef42e8e8adece098848fac53c721b6eb3818fc2"; + rev = "c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e"; flake = false; }; diff --git a/subprojects/wlroots.wrap b/subprojects/wlroots.wrap index ab7bf743..04427ba6 100644 --- a/subprojects/wlroots.wrap +++ b/subprojects/wlroots.wrap @@ -1,7 +1,7 @@ [wrap-git] directory = wlroots url = https://gitlab.freedesktop.org/wlroots/wlroots.git -revision = 5ef42e8e8adece098848fac53c721b6eb3818fc2 +revision = c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e depth = 1 diff_files = wlroots-meson-build.patch From 8e0eafc502625345c1943b13e7ff867fb6e6ef48 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 4 Oct 2023 15:05:20 +0100 Subject: [PATCH 046/513] deps: update wlroots --- subprojects/wlroots | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/wlroots b/subprojects/wlroots index c2aa7fd9..3406c1b1 160000 --- a/subprojects/wlroots +++ b/subprojects/wlroots @@ -1 +1 @@ -Subproject commit c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e +Subproject commit 3406c1b17a4a7e6d4e2a7d9c1176affa72bce1bc From 1b99a69dc11c3c8266559c3c20b2f4dac6621dcc Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 4 Oct 2023 14:06:09 +0000 Subject: [PATCH 047/513] [gha] Nix: update wlroots --- flake.lock | 8 ++++---- flake.nix | 2 +- subprojects/wlroots.wrap | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 524ca010..329aaec8 100644 --- a/flake.lock +++ b/flake.lock @@ -67,18 +67,18 @@ "flake": false, "locked": { "host": "gitlab.freedesktop.org", - "lastModified": 1695919988, - "narHash": "sha256-4RBgIZHaVqH0m1POnfzYRzwCWxifIKH4xQ0kCn2LGkA=", + "lastModified": 1696410538, + "narHash": "sha256-ecDhdYLXWHsxMv+EWG36mCNDvzRbu9qfjH7dLxL7aGM=", "owner": "wlroots", "repo": "wlroots", - "rev": "c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e", + "rev": "3406c1b17a4a7e6d4e2a7d9c1176affa72bce1bc", "type": "gitlab" }, "original": { "host": "gitlab.freedesktop.org", "owner": "wlroots", "repo": "wlroots", - "rev": "c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e", + "rev": "3406c1b17a4a7e6d4e2a7d9c1176affa72bce1bc", "type": "gitlab" } }, diff --git a/flake.nix b/flake.nix index d2eb35c5..4f0c1654 100644 --- a/flake.nix +++ b/flake.nix @@ -12,7 +12,7 @@ host = "gitlab.freedesktop.org"; owner = "wlroots"; repo = "wlroots"; - rev = "c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e"; + rev = "3406c1b17a4a7e6d4e2a7d9c1176affa72bce1bc"; flake = false; }; diff --git a/subprojects/wlroots.wrap b/subprojects/wlroots.wrap index 04427ba6..98f93a53 100644 --- a/subprojects/wlroots.wrap +++ b/subprojects/wlroots.wrap @@ -1,7 +1,7 @@ [wrap-git] directory = wlroots url = https://gitlab.freedesktop.org/wlroots/wlroots.git -revision = c2aa7fd965cb7ee8bed24f4122b720aca8f0fc1e +revision = 3406c1b17a4a7e6d4e2a7d9c1176affa72bce1bc depth = 1 diff_files = wlroots-meson-build.patch From 3d1a1679604e9de18a46a9a0819daf2044b08fa6 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Thu, 5 Oct 2023 01:31:13 +0100 Subject: [PATCH 048/513] wsrules: check for workspace ID matches on numbered workspaces fixes #3494 --- src/config/ConfigManager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 42611be3..b675f6ea 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1827,7 +1827,10 @@ SMonitorRule CConfigManager::getMonitorRuleFor(const std::string& name, const st } SWorkspaceRule CConfigManager::getWorkspaceRuleFor(CWorkspace* pWorkspace) { - const auto IT = std::find_if(m_dWorkspaceRules.begin(), m_dWorkspaceRules.end(), [&](const auto& other) { return other.workspaceName == pWorkspace->m_szName; }); + const auto WORKSPACEIDSTR = std::to_string(pWorkspace->m_iID); + const auto IT = std::find_if(m_dWorkspaceRules.begin(), m_dWorkspaceRules.end(), [&](const auto& other) { + return other.workspaceName == pWorkspace->m_szName || (pWorkspace->m_iID > 0 && WORKSPACEIDSTR == other.workspaceName); + }); if (IT == m_dWorkspaceRules.end()) return SWorkspaceRule{}; return *IT; From 24c04a8b7c874ead168bb2418f4325cb8bdaca5b Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Thu, 5 Oct 2023 16:57:54 +0100 Subject: [PATCH 049/513] crashreporter: avoid using empty CACHE_HOME --- src/debug/CrashReporter.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/debug/CrashReporter.cpp b/src/debug/CrashReporter.cpp index ed4357d2..1a28a780 100644 --- a/src/debug/CrashReporter.cpp +++ b/src/debug/CrashReporter.cpp @@ -130,7 +130,7 @@ void CrashReporter::createAndSaveCrash(int sig) { std::ofstream ofs; std::string path; - if (!CACHE_HOME) { + if (!CACHE_HOME || std::string(CACHE_HOME).empty()) { if (!std::filesystem::exists(std::string(HOME) + "/.hyprland")) { std::filesystem::create_directory(std::string(HOME) + "/.hyprland"); std::filesystem::permissions(std::string(HOME) + "/.hyprland", std::filesystem::perms::all, std::filesystem::perm_options::replace); @@ -139,7 +139,7 @@ void CrashReporter::createAndSaveCrash(int sig) { path = std::string(HOME) + "/.hyprland/hyprlandCrashReport" + std::to_string(PID) + ".txt"; ofs.open(path, std::ios::trunc); - } else if (CACHE_HOME) { + } else { if (!std::filesystem::exists(std::string(CACHE_HOME) + "/hyprland")) { std::filesystem::create_directory(std::string(CACHE_HOME) + "/hyprland"); std::filesystem::permissions(std::string(CACHE_HOME) + "/hyprland", std::filesystem::perms::all, std::filesystem::perm_options::replace); @@ -147,8 +147,6 @@ void CrashReporter::createAndSaveCrash(int sig) { path = std::string(CACHE_HOME) + "/hyprland/hyprlandCrashReport" + std::to_string(PID) + ".txt"; ofs.open(path, std::ios::trunc); - } else { - return; } ofs << finalCrashReport; From 4b3efc73c5d059e828f79952d80ff79c97521c3d Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Fri, 6 Oct 2023 01:11:47 +0100 Subject: [PATCH 050/513] events: fixup empty events not being sent on unmap Ref #3506 https://github.com/hyprwm/Hyprland/issues/3506#issuecomment-1749508111 --- src/Compositor.cpp | 4 ++++ src/events/Windows.cpp | 8 +++++++- src/managers/input/InputManager.cpp | 3 +-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 7fa45b07..66306888 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -893,6 +893,10 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) { g_pLayoutManager->getCurrentLayout()->bringWindowToTop(pWindow); if (!pWindow || !windowValidMapped(pWindow)) { + + if (!m_pLastWindow && !pWindow) + return; + const auto PLASTWINDOW = m_pLastWindow; m_pLastWindow = nullptr; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 54ffb37e..f78a2975 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -737,8 +737,14 @@ void Events::listener_unmapWindow(void* owner, void* data) { g_pInputManager->simulateMouseMovement(); else g_pCompositor->focusWindow(PWINDOWCANDIDATE); - } else { + } else g_pInputManager->simulateMouseMovement(); + + // CWindow::onUnmap will remove this window's active status, but we can't really do it above. + if (PWINDOW == g_pCompositor->m_pLastWindow || !g_pCompositor->m_pLastWindow) { + g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","}); + g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", ","}); + EMIT_HOOK_EVENT("activeWindow", (CWindow*)nullptr); } } else { Debug::log(LOG, "Unmapped was not focused, ignoring a refocus."); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index fe66b8ba..1b89f8fc 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -314,9 +314,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { wlr_seat_pointer_clear_focus(g_pCompositor->m_sSeat.seat); - if (refocus) { // if we are forcing a refocus, and we don't find a surface, clear the kb focus too! + if (refocus || !g_pCompositor->m_pLastWindow) // if we are forcing a refocus, and we don't find a surface, clear the kb focus too! g_pCompositor->focusWindow(nullptr); - } return; } From cb7dd1ac6ef250dc25b8e86b744dd47a24f12971 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Fri, 6 Oct 2023 14:00:05 +0100 Subject: [PATCH 051/513] layershell: avoid configure on unchanged size fixes #3496 --- src/render/Renderer.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index a685f735..efdf3ce6 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1274,18 +1274,18 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vectorlayerSurface; const auto PSTATE = &PLAYER->current; - if (exclusiveZone != (PSTATE->exclusive_zone > 0)) { + if (exclusiveZone != (PSTATE->exclusive_zone > 0)) continue; - } wlr_box bounds; - if (PSTATE->exclusive_zone == -1) { + if (PSTATE->exclusive_zone == -1) bounds = full_area; - } else { + else bounds = *usableArea; - } - wlr_box box = {.width = PSTATE->desired_width, .height = PSTATE->desired_height}; + const Vector2D OLDSIZE = {ls->geometry.width, ls->geometry.height}; + + wlr_box box = {.width = PSTATE->desired_width, .height = PSTATE->desired_height}; // Horizontal axis const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; if (box.width == 0) { @@ -1342,7 +1342,8 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vectoranchor, PSTATE->exclusive_zone, PSTATE->margin.top, PSTATE->margin.right, PSTATE->margin.bottom, PSTATE->margin.left); - wlr_layer_surface_v1_configure(ls->layerSurface, box.width, box.height); + if (Vector2D{box.width, box.height} != OLDSIZE) + wlr_layer_surface_v1_configure(ls->layerSurface, box.width, box.height); Debug::log(LOG, "LayerSurface {:x} arranged: x: {} y: {} w: {} h: {} with margins: t: {} l: {} r: {} b: {}", (uintptr_t)&ls, box.x, box.y, box.width, box.height, PSTATE->margin.top, PSTATE->margin.left, PSTATE->margin.right, PSTATE->margin.bottom); From 1afb00a01b7cab3e68f5af3ca6a7d7d86b8f913e Mon Sep 17 00:00:00 2001 From: ItsDrike Date: Fri, 6 Oct 2023 13:01:40 +0000 Subject: [PATCH 052/513] pluginapi: remove starting newline in demangled func name (#3502) --- src/plugins/PluginAPI.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/plugins/PluginAPI.cpp b/src/plugins/PluginAPI.cpp index a133de38..f79af312 100644 --- a/src/plugins/PluginAPI.cpp +++ b/src/plugins/PluginAPI.cpp @@ -301,7 +301,11 @@ APICALL std::vector HyprlandAPI::findFunctionsByName(HANDLE hand count++; } - return SYMBOLSDEMANGLED.substr(pos, SYMBOLSDEMANGLED.find('\n', pos + 1) - pos); + // Skip the newline char itself + if (pos != 0) + pos++; + + return SYMBOLSDEMANGLED.substr(pos, SYMBOLSDEMANGLED.find('\n', pos) - pos); }; if (SYMBOLS.empty()) { From 61d3d4dee7a4f9f68b4e7dd1e77ccd9acbed9a7c Mon Sep 17 00:00:00 2001 From: Jeremy Huang <66577496+thejch@users.noreply.github.com> Date: Fri, 6 Oct 2023 14:33:11 -0700 Subject: [PATCH 053/513] master: fix drop_at_cursor on workspace 2 (#3512) --- src/layout/MasterLayout.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 6fa168c4..0eeea16e 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -139,6 +139,8 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc if (*PDROPATCURSOR && g_pInputManager->dragMode == MBIND_MOVE) { // if dragging window to move, drop it at the cursor position instead of bottom/top of stack for (auto it = m_lMasterNodesData.begin(); it != m_lMasterNodesData.end(); ++it) { + if (it->workspaceID != pWindow->m_iWorkspaceID) + continue; const wlr_box box = it->pWindow->getWindowIdealBoundingBoxIgnoreReserved(); if (wlr_box_contains_point(&box, MOUSECOORDS.x, MOUSECOORDS.y)) { // TODO: Deny when not using mouse switch (orientation) { From 38e242953df06b7b90a09fd7a1480a9cfcdd6ba8 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sat, 7 Oct 2023 02:28:23 +0100 Subject: [PATCH 054/513] animationmgr: damage floating windows on workspace anim fixes #3514 --- src/managers/AnimationManager.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 64cb1c0c..db3ebe52 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -93,6 +93,12 @@ void CAnimationManager::tick() { if (!PMONITOR) continue; WLRBOXPREV = {(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y}; + + // TODO: just make this into a damn callback already vax... + for (auto& w : g_pCompositor->m_vWindows) { + if (!w->isHidden() && w->m_bIsMapped && w->m_bIsFloating) + g_pHyprRenderer->damageWindow(w.get()); + } } else if (PLAYER) { WLRBOXPREV = PLAYER->geometry; PMONITOR = g_pCompositor->getMonitorFromVector(Vector2D(PLAYER->geometry.x, PLAYER->geometry.y) + Vector2D(PLAYER->geometry.width, PLAYER->geometry.height) / 2.f); From 7d7565e7ecb65463d68ebe0d2654ad346d61acd8 Mon Sep 17 00:00:00 2001 From: DaniD3v Date: Sat, 7 Oct 2023 15:08:38 +0200 Subject: [PATCH 055/513] renderer: add force_wallpaper instead of no_hypr_chan (#3459) --- src/config/ConfigManager.cpp | 2 +- src/render/OpenGL.cpp | 32 ++++++++++++++++++-------------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index b675f6ea..23efe77e 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -91,8 +91,8 @@ void CConfigManager::setDefaultVars() { configValues["misc:disable_hyprland_logo"].intValue = 0; configValues["misc:disable_splash_rendering"].intValue = 0; - configValues["misc:disable_hypr_chan"].intValue = 0; configValues["misc:force_hypr_chan"].intValue = 0; + configValues["misc:force_default_wallpaper"].intValue = -1; configValues["misc:vfr"].intValue = 1; configValues["misc:vrr"].intValue = 0; configValues["misc:mouse_move_enables_dpms"].intValue = 0; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 5d513f31..64703205 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1762,34 +1762,37 @@ void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!"); - static auto* const PNOSPLASH = &g_pConfigManager->getConfigValuePtr("misc:disable_splash_rendering")->intValue; - static auto* const PDISABLEHYPRCHAN = &g_pConfigManager->getConfigValuePtr("misc:disable_hypr_chan")->intValue; - static auto* const PFORCEHYPRCHAN = &g_pConfigManager->getConfigValuePtr("misc:force_hypr_chan")->intValue; + static auto* const PNOSPLASH = &g_pConfigManager->getConfigValuePtr("misc:disable_splash_rendering")->intValue; + static auto* const PFORCEHYPRCHAN = &g_pConfigManager->getConfigValuePtr("misc:force_hypr_chan")->intValue; + static auto* const PFORCEWALLPAPER = &g_pConfigManager->getConfigValuePtr("misc:force_default_wallpaper")->intValue; - std::random_device dev; - std::mt19937 engine(dev()); - std::uniform_int_distribution<> distribution(0, 2); - std::uniform_int_distribution<> distribution2(0, 1); - - const bool USEANIME = *PFORCEHYPRCHAN || distribution(engine) == 0; // 66% for anime + const auto FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, -1L, 2L); // release the last tex if exists const auto PTEX = &m_mMonitorBGTextures[pMonitor]; PTEX->destroyTexture(); PTEX->allocate(); - Debug::log(LOG, "Allocated texture for BGTex"); // TODO: use relative paths to the installation // or configure the paths at build time + std::string texPath = "/usr/share/hyprland/wall_"; + std::string prefixes[] = {"", "anime_", "anime2_"}; // get the adequate tex - std::string texPath = "/usr/share/hyprland/wall_"; - if (!*PDISABLEHYPRCHAN) - texPath += std::string(USEANIME ? (distribution2(engine) == 0 ? "anime_" : "anime2_") : ""); + if (FORCEWALLPAPER == -1) { + std::random_device dev; + std::mt19937 engine(dev()); + std::uniform_int_distribution<> distribution(0, 2); + std::uniform_int_distribution<> distribution_anime(1, 2); - // check if wallpapers exist + if (PFORCEHYPRCHAN) + texPath += prefixes[distribution_anime(engine)]; + else + texPath += prefixes[distribution(engine)]; + } else + texPath += prefixes[FORCEWALLPAPER]; Vector2D textureSize; if (pMonitor->vecTransformedSize.x > 3850) { @@ -1803,6 +1806,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { texPath += "2K.png"; } + // check if wallpapers exist if (!std::filesystem::exists(texPath)) { // try local texPath = texPath.substr(0, 5) + "local/" + texPath.substr(5); From 728a8bb48e0f7de1cbe1ad13fb469754c3d0bc97 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sat, 7 Oct 2023 15:55:33 +0100 Subject: [PATCH 056/513] config: mention force_default_wallpaper in default configs --- example/hyprland.conf | 5 +++++ src/config/defaultConfig.hpp | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/example/hyprland.conf b/example/hyprland.conf index d28b8463..01dbfda9 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -102,6 +102,11 @@ gestures { workspace_swipe = false } +misc { + # See https://wiki.hyprland.org/Configuring/Variables/ for more + force_default_wallpaper = -1 # Set to 0 to disable the anime mascot wallpapers +} + # Example per-device config # See https://wiki.hyprland.org/Configuring/Keywords/#per-device-input-configs for more device:epic-mouse-v1 { diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 6c30e19c..5e7588fc 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -111,6 +111,11 @@ gestures { workspace_swipe = off } +misc { + # See https://wiki.hyprland.org/Configuring/Variables/ for more + force_default_wallpaper = -1 # Set to 0 to disable the anime mascot wallpapers +} + # Example per-device config # See https://wiki.hyprland.org/Configuring/Keywords/#executing for more device:epic-mouse-v1 { From 499df49f7b28f9e3be9b1c53843fd5c465dec60b Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Sun, 8 Oct 2023 12:49:15 +0000 Subject: [PATCH 057/513] dispatchers: fix extra monitor offset when snapping floating (#3520) modified: src/managers/KeybindManager.cpp --- src/managers/KeybindManager.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 1a7ebafc..c86804d6 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1109,20 +1109,20 @@ void CKeybindManager::moveActiveTo(std::string args) { return; if (PLASTWINDOW->m_bIsFloating) { - auto vPos = PLASTWINDOW->m_vRealPosition.goalv(); + Vector2D vPos; const auto PMONITOR = g_pCompositor->getMonitorFromID(PLASTWINDOW->m_iMonitorID); const auto BORDERSIZE = PLASTWINDOW->getRealBorderSize(); switch (arg) { - case 'l': vPos.x = PMONITOR->vecReservedTopLeft.x + BORDERSIZE; break; - case 'r': vPos.x = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PLASTWINDOW->m_vRealSize.goalv().x - BORDERSIZE; break; + case 'l': vPos.x = PMONITOR->vecReservedTopLeft.x + BORDERSIZE + PMONITOR->vecPosition.x; break; + case 'r': vPos.x = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PLASTWINDOW->m_vRealSize.goalv().x - BORDERSIZE + PMONITOR->vecPosition.x; break; case 't': - case 'u': vPos.y = PMONITOR->vecReservedTopLeft.y + BORDERSIZE; break; + case 'u': vPos.y = PMONITOR->vecReservedTopLeft.y + BORDERSIZE + PMONITOR->vecPosition.y; break; case 'b': - case 'd': vPos.y = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PLASTWINDOW->m_vRealSize.goalv().y - BORDERSIZE; break; + case 'd': vPos.y = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PLASTWINDOW->m_vRealSize.goalv().y - BORDERSIZE + PMONITOR->vecPosition.y; break; } - PLASTWINDOW->m_vRealPosition = vPos + PMONITOR->vecPosition; + PLASTWINDOW->m_vRealPosition = Vector2D(vPos.x != 0 ? vPos.x : PLASTWINDOW->m_vRealPosition.goalv().x, vPos.y != 0 ? vPos.y : PLASTWINDOW->m_vRealPosition.goalv().y); return; } From 7f8e0a131883ffa44ce85b2353873c2257aebbf7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Lewandowski?= <49685661+FakeMichau@users.noreply.github.com> Date: Mon, 9 Oct 2023 13:28:58 +0200 Subject: [PATCH 058/513] dwindle: Avoid rounding errors in window position (#3524) * Avoid rounding errors in window position * Fix naming scheme * Fix unwanted window movement --- src/layout/DwindleLayout.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 1ce47d96..a0482ba8 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -4,9 +4,6 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverride, bool verticalOverride) { if (children[0]) { - - const auto REVERSESPLITRATIO = 2.f - splitRatio; - static auto* const PSMARTSPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:smart_split")->intValue; static auto* const PPRESERVESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:preserve_split")->intValue; static auto* const PFLMULT = &g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier")->floatValue; @@ -24,16 +21,18 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverrid if (SPLITSIDE) { // split left/right + int const FIRSTSIZE = std::round(size.x / 2 * splitRatio); children[0]->position = position; - children[0]->size = Vector2D(size.x / 2.f * splitRatio, size.y); - children[1]->position = Vector2D(position.x + size.x / 2.f * splitRatio, position.y); - children[1]->size = Vector2D(size.x / 2.f * REVERSESPLITRATIO, size.y); + children[0]->size = Vector2D(FIRSTSIZE, size.y); + children[1]->position = Vector2D(position.x + FIRSTSIZE, position.y); + children[1]->size = Vector2D(size.x - FIRSTSIZE, size.y); } else { // split top/bottom + int const FIRSTSIZE = std::round(size.y / 2 * splitRatio); children[0]->position = position; - children[0]->size = Vector2D(size.x, size.y / 2.f * splitRatio); - children[1]->position = Vector2D(position.x, position.y + size.y / 2.f * splitRatio); - children[1]->size = Vector2D(size.x, size.y / 2.f * REVERSESPLITRATIO); + children[0]->size = Vector2D(size.x, FIRSTSIZE); + children[1]->position = Vector2D(position.x, position.y + FIRSTSIZE); + children[1]->size = Vector2D(size.x, size.y - FIRSTSIZE); } children[0]->recalcSizePosRecursive(force); From df0c8e0f7a580e18eebbe934c00124a08b426583 Mon Sep 17 00:00:00 2001 From: Roberto Previdi Date: Mon, 9 Oct 2023 21:28:22 +0200 Subject: [PATCH 059/513] workspacerules: Add a persistent workspace rule (#3530) * add persistent flag to workspace rules * get rid of unused ws->indestructible flag --- src/Compositor.cpp | 5 ++++- src/config/ConfigManager.cpp | 2 ++ src/config/ConfigManager.hpp | 1 + src/helpers/Workspace.hpp | 3 --- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 66306888..42c2ab35 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1188,8 +1188,11 @@ void CCompositor::sanityCheckWorkspaces() { auto it = m_vWorkspaces.begin(); while (it != m_vWorkspaces.end()) { - if ((*it)->m_bIndestructible) + const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(it->get()); + if (WORKSPACERULE.isPersistent) { + ++it; continue; + } const auto WINDOWSONWORKSPACE = getWindowsOnWorkspace((*it)->m_iID); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 23efe77e..f21ad9f3 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1177,6 +1177,8 @@ void CConfigManager::handleWorkspaceRules(const std::string& command, const std: wsRule.monitor = rule.substr(delim + 8); else if ((delim = rule.find("default:")) != std::string::npos) wsRule.isDefault = configStringToInt(rule.substr(delim + 8)); + else if ((delim = rule.find("persistent:")) != std::string::npos) + wsRule.isPersistent = configStringToInt(rule.substr(delim + 11)); }; size_t pos = 0; diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 390079d3..e637979d 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -41,6 +41,7 @@ struct SWorkspaceRule { std::string workspaceName = ""; int workspaceId = -1; bool isDefault = false; + bool isPersistent = false; std::optional gapsIn; std::optional gapsOut; std::optional borderSize; diff --git a/src/helpers/Workspace.hpp b/src/helpers/Workspace.hpp index 2e810b9a..cbdbc07a 100644 --- a/src/helpers/Workspace.hpp +++ b/src/helpers/Workspace.hpp @@ -50,9 +50,6 @@ class CWorkspace { bool m_bDefaultFloating = false; bool m_bDefaultPseudo = false; - // don't destroy in sanity check - bool m_bIndestructible = false; - // last monitor (used on reconnect) std::string m_szLastMonitor = ""; From 8abb6e1cee3e967ff414af0d6a1a31ebced95f5b Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Mon, 9 Oct 2023 23:51:55 +0100 Subject: [PATCH 060/513] screencopy: enhance error logging --- src/protocols/Screencopy.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 61f76285..9839b660 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -265,18 +265,21 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou const auto PBUFFER = wlr_buffer_from_resource(buffer); if (!PBUFFER) { + Debug::log(ERR, "[sc] invalid buffer in {:x}", (uintptr_t)PFRAME); wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer"); removeFrame(PFRAME); return; } if (PBUFFER->width != PFRAME->box.width || PBUFFER->height != PFRAME->box.height) { + Debug::log(ERR, "[sc] invalid dimensions in {:x}", (uintptr_t)PFRAME); wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer dimensions"); removeFrame(PFRAME); return; } if (PFRAME->buffer) { + Debug::log(ERR, "[sc] buffer used in {:x}", (uintptr_t)PFRAME); wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_ALREADY_USED, "frame already used"); removeFrame(PFRAME); return; @@ -290,6 +293,7 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou PFRAME->bufferCap = WLR_BUFFER_CAP_DMABUF; if (dmabufAttrs.format != PFRAME->dmabufFormat) { + Debug::log(ERR, "[sc] invalid buffer dma format in {:x}", (uintptr_t)PFRAME); wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format"); removeFrame(PFRAME); return; @@ -298,15 +302,18 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou wlr_buffer_end_data_ptr_access(PBUFFER); if (wlrBufferAccessFormat != PFRAME->shmFormat) { + Debug::log(ERR, "[sc] invalid buffer shm format in {:x}", (uintptr_t)PFRAME); wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer format"); removeFrame(PFRAME); return; } else if ((int)wlrBufferAccessStride != PFRAME->shmStride) { + Debug::log(ERR, "[sc] invalid buffer shm stride in {:x}", (uintptr_t)PFRAME); wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer stride"); removeFrame(PFRAME); return; } } else { + Debug::log(ERR, "[sc] invalid buffer type in {:x}", (uintptr_t)PFRAME); wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer type"); removeFrame(PFRAME); return; @@ -382,11 +389,13 @@ void CScreencopyProtocolManager::shareFrame(SScreencopyFrame* frame) { uint32_t flags = 0; if (frame->bufferCap == WLR_BUFFER_CAP_DMABUF) { if (!copyFrameDmabuf(frame)) { + Debug::log(ERR, "[sc] dmabuf copy failed in {:x}", (uintptr_t)frame); zwlr_screencopy_frame_v1_send_failed(frame->resource); return; } } else { if (!copyFrameShm(frame, &now)) { + Debug::log(ERR, "[sc] shm copy failed in {:x}", (uintptr_t)frame); zwlr_screencopy_frame_v1_send_failed(frame->resource); return; } From ac1bd47653f7d07a77fb3e0e32c0863bb0dced2e Mon Sep 17 00:00:00 2001 From: Philip Damianik <39028343+pdamianik@users.noreply.github.com> Date: Tue, 10 Oct 2023 18:34:28 +0200 Subject: [PATCH 061/513] dispatchers: Add option to center the cursor on the focused window when switching workspaces (#3528) * Add option for centering on workspace when switching workspace * Add option for centering on workspace when switching workspace --------- Co-authored-by: vaxerski <43317083+vaxerski@users.noreply.github.com> --- src/config/ConfigManager.cpp | 1 + src/managers/KeybindManager.cpp | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f21ad9f3..4e039ee0 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -232,6 +232,7 @@ void CConfigManager::setDefaultVars() { configValues["binds:scroll_event_delay"].intValue = 300; configValues["binds:workspace_back_and_forth"].intValue = 0; configValues["binds:allow_workspace_cycles"].intValue = 0; + configValues["binds:workspace_center_on"].intValue = 1; configValues["binds:focus_preferred_method"].intValue = 0; configValues["binds:ignore_group_lock"].intValue = 0; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index c86804d6..eb100870 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -804,6 +804,7 @@ void CKeybindManager::changeworkspace(std::string args) { // the current workspace will instead switch to the previous. static auto* const PBACKANDFORTH = &g_pConfigManager->getConfigValuePtr("binds:workspace_back_and_forth")->intValue; static auto* const PALLOWWORKSPACECYCLES = &g_pConfigManager->getConfigValuePtr("binds:allow_workspace_cycles")->intValue; + static auto* const PWORKSPACECENTERON = &g_pConfigManager->getConfigValuePtr("binds:workspace_center_on")->intValue; const auto PMONITOR = g_pCompositor->m_pLastMonitor; const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); @@ -863,9 +864,13 @@ void CKeybindManager::changeworkspace(std::string args) { PMONITORWORKSPACEOWNER->changeWorkspace(pWorkspaceToChangeTo, false, true); if (PMONITOR != PMONITORWORKSPACEOWNER) { - g_pCompositor->warpCursorTo(PMONITORWORKSPACEOWNER->middle()); - if (const auto PLAST = pWorkspaceToChangeTo->getLastFocusedWindow(); PLAST) + Vector2D middle = PMONITORWORKSPACEOWNER->middle(); + if (const auto PLAST = pWorkspaceToChangeTo->getLastFocusedWindow(); PLAST) { g_pCompositor->focusWindow(PLAST); + if (*PWORKSPACECENTERON == 1) + middle = PLAST->middle(); + } + g_pCompositor->warpCursorTo(middle); } if (BISWORKSPACECURRENT) { @@ -1083,7 +1088,7 @@ void CKeybindManager::swapActive(std::string args) { return; g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, PWINDOWTOCHANGETO); - g_pCompositor->warpCursorTo(PLASTWINDOW->m_vRealPosition.vec() + PLASTWINDOW->m_vRealSize.vec() / 2.0); + g_pCompositor->warpCursorTo(PLASTWINDOW->middle()); } void CKeybindManager::moveActiveTo(std::string args) { From d537815d43c74a4e9214c4e7480c20047d297307 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Tue, 10 Oct 2023 16:42:45 +0000 Subject: [PATCH 062/513] groups: create group and groupbar config sections (#3522) * config: create group section modified: src/Compositor.cpp modified: src/config/ConfigManager.cpp modified: src/layout/DwindleLayout.cpp modified: src/layout/MasterLayout.cpp modified: src/managers/KeybindManager.cpp modified: src/managers/input/InputManager.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * separate group border and groupbar colors modified: src/Compositor.cpp modified: src/config/ConfigManager.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * add new line modified: config/ConfigManager.cpp --- src/Compositor.cpp | 8 +-- src/config/ConfigManager.cpp | 52 ++++++++++++------- src/layout/DwindleLayout.cpp | 2 +- src/layout/MasterLayout.cpp | 2 +- src/managers/KeybindManager.cpp | 5 +- src/managers/input/InputManager.cpp | 2 +- .../decorations/CHyprGroupBarDecoration.cpp | 34 ++++++------ 7 files changed, 59 insertions(+), 46 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 42c2ab35..b9be9f18 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1744,10 +1744,10 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) { static auto* const INACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.inactive_border")->data.get(); static auto* const NOGROUPACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.nogroup_border_active")->data.get(); static auto* const NOGROUPINACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.nogroup_border")->data.get(); - static auto* const GROUPACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.group_border_active")->data.get(); - static auto* const GROUPINACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.group_border")->data.get(); - static auto* const GROUPACTIVELOCKEDCOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.group_border_locked_active")->data.get(); - static auto* const GROUPINACTIVELOCKEDCOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.group_border_locked")->data.get(); + static auto* const GROUPACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:col.border_active")->data.get(); + static auto* const GROUPINACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:col.border_inactive")->data.get(); + static auto* const GROUPACTIVELOCKEDCOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:col.border_locked_active")->data.get(); + static auto* const GROUPINACTIVELOCKEDCOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:col.border_locked_inactive")->data.get(); static auto* const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue; static auto* const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue; static auto* const PFULLSCREENALPHA = &g_pConfigManager->getConfigValuePtr("decoration:fullscreen_opacity")->floatValue; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 4e039ee0..2d19389e 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -15,14 +15,20 @@ extern "C" char** environ; CConfigManager::CConfigManager() { - configValues["general:col.active_border"].data = std::make_shared(0xffffffff); - configValues["general:col.inactive_border"].data = std::make_shared(0xff444444); - configValues["general:col.nogroup_border"].data = std::make_shared(0xffffaaff); - configValues["general:col.nogroup_border_active"].data = std::make_shared(0xffff00ff); - configValues["general:col.group_border"].data = std::make_shared(0x66777700); - configValues["general:col.group_border_active"].data = std::make_shared(0x66ffff00); - configValues["general:col.group_border_locked"].data = std::make_shared(0x66775500); - configValues["general:col.group_border_locked_active"].data = std::make_shared(0x66ff5500); + configValues["general:col.active_border"].data = std::make_shared(0xffffffff); + configValues["general:col.inactive_border"].data = std::make_shared(0xff444444); + configValues["general:col.nogroup_border"].data = std::make_shared(0xffffaaff); + configValues["general:col.nogroup_border_active"].data = std::make_shared(0xffff00ff); + + configValues["group:col.border_active"].data = std::make_shared(0x66ffff00); + configValues["group:col.border_inactive"].data = std::make_shared(0x66777700); + configValues["group:col.border_locked_active"].data = std::make_shared(0x66ff5500); + configValues["group:col.border_locked_inactive"].data = std::make_shared(0x66775500); + + configValues["group:groupbar:col.active"].data = std::make_shared(0x66ffff00); + configValues["group:groupbar:col.inactive"].data = std::make_shared(0x66777700); + configValues["group:groupbar:col.locked_active"].data = std::make_shared(0x66ff5500); + configValues["group:groupbar:col.locked_inactive"].data = std::make_shared(0x66775500); setDefaultVars(); setDefaultAnimationVars(); @@ -76,10 +82,6 @@ void CConfigManager::setDefaultVars() { ((CGradientValueData*)configValues["general:col.inactive_border"].data.get())->reset(0xff444444); ((CGradientValueData*)configValues["general:col.nogroup_border"].data.get())->reset(0xff444444); ((CGradientValueData*)configValues["general:col.nogroup_border_active"].data.get())->reset(0xffff00ff); - ((CGradientValueData*)configValues["general:col.group_border"].data.get())->reset(0x66777700); - ((CGradientValueData*)configValues["general:col.group_border_active"].data.get())->reset(0x66ffff00); - ((CGradientValueData*)configValues["general:col.group_border_locked"].data.get())->reset(0x66775500); - ((CGradientValueData*)configValues["general:col.group_border_locked_active"].data.get())->reset(0x66ff5500); configValues["general:cursor_inactive_timeout"].intValue = 0; configValues["general:no_cursor_warps"].intValue = 0; configValues["general:no_focus_fallback"].intValue = 0; @@ -114,17 +116,29 @@ void CConfigManager::setDefaultVars() { configValues["misc:cursor_zoom_factor"].floatValue = 1.f; configValues["misc:cursor_zoom_rigid"].intValue = 0; configValues["misc:allow_session_lock_restore"].intValue = 0; - configValues["misc:groupbar_scrolling"].intValue = 1; - configValues["misc:group_insert_after_current"].intValue = 1; - configValues["misc:group_focus_removed_window"].intValue = 1; - configValues["misc:render_titles_in_groupbar"].intValue = 1; - configValues["misc:groupbar_titles_font_size"].intValue = 8; - configValues["misc:groupbar_gradients"].intValue = 1; configValues["misc:close_special_on_empty"].intValue = 1; - configValues["misc:groupbar_text_color"].intValue = 0xffffffff; configValues["misc:background_color"].intValue = 0xff111111; configValues["misc:new_window_takes_over_fullscreen"].intValue = 0; + ((CGradientValueData*)configValues["group:col.border_active"].data.get())->reset(0x66ffff00); + ((CGradientValueData*)configValues["group:col.border_inactive"].data.get())->reset(0x66777700); + ((CGradientValueData*)configValues["group:col.border_locked_active"].data.get())->reset(0x66ff5500); + ((CGradientValueData*)configValues["group:col.border_locked_inactive"].data.get())->reset(0x66775500); + + configValues["group:insert_after_current"].intValue = 1; + configValues["group:focus_removed_window"].intValue = 1; + + configValues["group:groupbar:font_size"].intValue = 8; + configValues["group:groupbar:gradients"].intValue = 1; + configValues["group:groupbar:render_titles"].intValue = 1; + configValues["group:groupbar:scrolling"].intValue = 1; + configValues["group:groupbar:text_color"].intValue = 0xffffffff; + + ((CGradientValueData*)configValues["group:groupbar:col.active"].data.get())->reset(0x66ffff00); + ((CGradientValueData*)configValues["group:groupbar:col.inactive"].data.get())->reset(0x66777700); + ((CGradientValueData*)configValues["group:groupbar:col.locked_active"].data.get())->reset(0x66ff5500); + ((CGradientValueData*)configValues["group:groupbar:col.locked_inactive"].data.get())->reset(0x66775500); + configValues["debug:int"].intValue = 0; configValues["debug:log_damage"].intValue = 0; configValues["debug:overlay"].intValue = 0; diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index a0482ba8..b034557e 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -336,7 +336,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire if (INDEX == -1) std::swap(pWindow->m_sGroupData.pNextWindow->m_sGroupData.head, pWindow->m_sGroupData.head); } else { - static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("misc:group_insert_after_current")->intValue; + static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue; (*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow); } diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 0eeea16e..2de43d04 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -118,7 +118,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc if (INDEX == -1) std::swap(pWindow->m_sGroupData.pNextWindow->m_sGroupData.head, pWindow->m_sGroupData.head); } else { - static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("misc:group_insert_after_current")->intValue; + static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue; (*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow); } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index eb100870..52581b62 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1968,7 +1968,7 @@ void CKeybindManager::moveWindowIntoGroup(CWindow* pWindow, CWindow* pWindowInDi g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow); // This removes groupped property! - static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("misc:group_insert_after_current")->intValue; + static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue; pWindowInDirection = *USECURRPOS ? pWindowInDirection : pWindowInDirection->getGroupTail(); pWindowInDirection->insertWindowToGroup(pWindow); @@ -1980,8 +1980,7 @@ void CKeybindManager::moveWindowIntoGroup(CWindow* pWindow, CWindow* pWindowInDi } void CKeybindManager::moveWindowOutOfGroup(CWindow* pWindow, const std::string& dir) { - - static auto* const BFOCUSREMOVEDWINDOW = &g_pConfigManager->getConfigValuePtr("misc:group_focus_removed_window")->intValue; + static auto* const BFOCUSREMOVEDWINDOW = &g_pConfigManager->getConfigValuePtr("group:focus_removed_window")->intValue; const auto PWINDOWPREV = pWindow->getGroupPrevious(); eDirection direction; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 1b89f8fc..f79278e3 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -621,7 +621,7 @@ void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) { void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) { static auto* const PSCROLLFACTOR = &g_pConfigManager->getConfigValuePtr("input:touchpad:scroll_factor")->floatValue; - static auto* const PGROUPBARSCROLLING = &g_pConfigManager->getConfigValuePtr("misc:groupbar_scrolling")->intValue; + static auto* const PGROUPBARSCROLLING = &g_pConfigManager->getConfigValuePtr("group:groupbar:scrolling")->intValue; auto factor = (*PSCROLLFACTOR <= 0.f || e->source != WLR_AXIS_SOURCE_FINGER ? 1.f : *PSCROLLFACTOR); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 70d4ed93..4d3200a6 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -34,8 +34,8 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) { const auto WORKSPACEOFFSET = PWORKSPACE && !pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D(); - static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("misc:render_titles_in_groupbar")->intValue; - static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("misc:groupbar_titles_font_size")->intValue; + static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("group:groupbar:render_titles")->intValue; + static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue; if (pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) { // we draw 3px above the window's border with 3px @@ -84,9 +84,9 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& // get how many bars we will draw int barsToDraw = m_dwGroupMembers.size(); - static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("misc:render_titles_in_groupbar")->intValue; - static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("misc:groupbar_titles_font_size")->intValue; - static auto* const PGRADIENTS = &g_pConfigManager->getConfigValuePtr("misc:groupbar_gradients")->intValue; + static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("group:groupbar:render_titles")->intValue; + static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue; + static auto* const PGRADIENTS = &g_pConfigManager->getConfigValuePtr("group:groupbar:gradients")->intValue; const int BORDERSIZE = m_pWindow->getRealBorderSize(); @@ -108,10 +108,10 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& scaleBox(&rect, pMonitor->scale); - static auto* const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("general:col.group_border_active")->data; - static auto* const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("general:col.group_border")->data; - static auto* const PGROUPCOLACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("general:col.group_border_locked_active")->data; - static auto* const PGROUPCOLINACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("general:col.group_border_locked")->data; + static auto* const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.active")->data; + static auto* const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.inactive")->data; + static auto* const PGROUPCOLACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_active")->data; + static auto* const PGROUPCOLINACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_inactive")->data; const bool GROUPLOCKED = m_pWindow->getGroupHead()->m_sGroupData.locked; const auto* const PCOLACTIVE = GROUPLOCKED ? PGROUPCOLACTIVELOCKED : PGROUPCOLACTIVE; @@ -156,8 +156,8 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& } SWindowDecorationExtents CHyprGroupBarDecoration::getWindowDecorationReservedArea() { - static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("misc:render_titles_in_groupbar")->intValue; - static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("misc:groupbar_titles_font_size")->intValue; + static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("group:groupbar:render_titles")->intValue; + static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue; return SWindowDecorationExtents{{0, BAR_INDICATOR_HEIGHT + BAR_PADDING_OUTER_VERT * 2 + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0)}, {}}; } @@ -180,8 +180,8 @@ CTitleTex::CTitleTex(CWindow* pWindow, const Vector2D& bufferSize) { const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, bufferSize.x, bufferSize.y); const auto CAIRO = cairo_create(CAIROSURFACE); - static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("misc:groupbar_titles_font_size")->intValue; - static auto* const PTEXTCOLOR = &g_pConfigManager->getConfigValuePtr("misc:groupbar_text_color")->intValue; + static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue; + static auto* const PTEXTCOLOR = &g_pConfigManager->getConfigValuePtr("group:groupbar:text_color")->intValue; const CColor COLOR = CColor(*PTEXTCOLOR); @@ -289,10 +289,10 @@ void CHyprGroupBarDecoration::refreshGradients() { if (m_tGradientActive.m_iTexID > 0) return; - static auto* const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("general:col.group_border_active")->data; - static auto* const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("general:col.group_border")->data; - static auto* const PGROUPCOLACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("general:col.group_border_locked_active")->data; - static auto* const PGROUPCOLINACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("general:col.group_border_locked")->data; + static auto* const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.active")->data; + static auto* const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.inactive")->data; + static auto* const PGROUPCOLACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_active")->data; + static auto* const PGROUPCOLINACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_inactive")->data; const bool GROUPLOCKED = m_pWindow->getGroupHead()->m_sGroupData.locked; const auto* const PCOLACTIVE = GROUPLOCKED ? PGROUPCOLACTIVELOCKED : PGROUPCOLACTIVE; From bf94df7b00eefe67780c2049a3f8f6e034b3c73e Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Tue, 10 Oct 2023 19:59:42 +0100 Subject: [PATCH 063/513] makefile: set correct perms on includes --- Makefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Makefile b/Makefile index 07187d73..0dfa7afa 100644 --- a/Makefile +++ b/Makefile @@ -72,6 +72,9 @@ install: cp ./assets/hyprland-portals.conf ${PREFIX}/share/xdg-desktop-portal/ if [ -d /usr/share/pkgconfig ]; then cp ./build/hyprland.pc /usr/share/pkgconfig 2>/dev/null || true; fi + chmod -R 755 ${PREFIX}/include/hyprland + chmod 755 ${PREFIX}/share/pkgconfig + cleaninstall: echo -en "$(MAKE) cleaninstall has been DEPRECATED, you should avoid using it in the future.\nRunning $(MAKE) install instead...\n" $(MAKE) install @@ -126,6 +129,9 @@ pluginenv: cp ./build/hyprland.pc ${PREFIX}/share/pkgconfig if [ -d /usr/share/pkgconfig ]; then cp ./build/hyprland.pc /usr/share/pkgconfig 2>/dev/null || true; fi + chmod -R 755 ${PREFIX}/include/hyprland + chmod 755 ${PREFIX}/share/pkgconfig + configdebug: $(MAKE) fixwlr From 1a0909aa203312b6ccfe8c34ddb6cbec63ca5199 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Tue, 10 Oct 2023 20:01:02 +0100 Subject: [PATCH 064/513] makefile: set 777 for /build perms --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 0dfa7afa..50e82405 100644 --- a/Makefile +++ b/Makefile @@ -3,22 +3,22 @@ PREFIX = /usr/local legacyrenderer: cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` - chmod 755 ./build/Hyprland + chmod -R 777 ./build legacyrendererdebug: cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -DLEGACY_RENDERER:BOOL=true -S . -B ./build -G Ninja cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` - chmod 755 ./build/Hyprland + chmod -R 777 ./build release: cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` - chmod 755 ./build/Hyprland + chmod -R 777 ./build debug: cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Debug -S . -B ./build -G Ninja cmake --build ./build --config Debug --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` - chmod 755 ./build/Hyprland + chmod -R 777 ./build clear: rm -rf build From 3219c84433874c3b852a254b7b3047f0e19913d8 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Tue, 10 Oct 2023 20:03:02 +0100 Subject: [PATCH 065/513] makefile: set perms for built subprojects in pluginenv --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 50e82405..6a96015c 100644 --- a/Makefile +++ b/Makefile @@ -115,6 +115,9 @@ pluginenv: meson setup subprojects/wlroots/build subprojects/wlroots --prefix=${PREFIX} --buildtype=release -Dwerror=false -Dexamples=false ninja -C subprojects/wlroots/build/ + chmod -R 777 subprojects/udis86 + chmod -R 777 subprojects/wlroots + cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja mkdir -p ${PREFIX}/include/hyprland From 914851b91aeb450592e2d62749169298ac48fb0c Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Tue, 10 Oct 2023 20:21:57 +0100 Subject: [PATCH 066/513] internal: better versioning (#3543) * better versioning * meson: better versioning * nix: better versioning --------- Co-authored-by: Mihai Fufezan --- .gitignore | 2 ++ CMakeLists.txt | 30 ++---------------------------- meson.build | 12 ++---------- nix/default.nix | 12 +++++++++--- nix/patches/meson-build.patch | 33 ++++++++++++++------------------- scripts/generateVersion.sh | 14 ++++++++++++++ src/macros.hpp | 27 ++++++++------------------- src/version.h.in | 5 +++++ 8 files changed, 56 insertions(+), 79 deletions(-) create mode 100755 scripts/generateVersion.sh create mode 100644 src/version.h.in diff --git a/.gitignore b/.gitignore index 96fd6c87..dfee530e 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,5 @@ gmon.out *.tar.gz PKGBUILD + +src/version.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b3bc5526..29eccd64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,34 +21,8 @@ message(STATUS "Gathering git info") # Get git info # hash and branch execute_process( - COMMAND git rev-parse --abbrev-ref HEAD - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE GIT_BRANCH - OUTPUT_STRIP_TRAILING_WHITESPACE) - -execute_process( - COMMAND git rev-parse HEAD - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE GIT_COMMIT_HASH - OUTPUT_STRIP_TRAILING_WHITESPACE) - -execute_process( - COMMAND sh -c "git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1 | sed -e 's/#//g' -e 's/\"//g'" - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE GIT_COMMIT_MESSAGE - OUTPUT_STRIP_TRAILING_WHITESPACE) - -execute_process( - COMMAND sh -c "git diff-index --quiet HEAD -- || echo \"dirty\"" - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE GIT_DIRTY - OUTPUT_STRIP_TRAILING_WHITESPACE) - -execute_process( - COMMAND sh -c "git describe --tags" - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE GIT_TAG - OUTPUT_STRIP_TRAILING_WHITESPACE) + COMMAND ./scripts/generateVersion.sh + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) # # diff --git a/meson.build b/meson.build index d515621e..726933bc 100644 --- a/meson.build +++ b/meson.build @@ -20,22 +20,12 @@ else error('Could not configure current C++ compiler (' + cpp_compiler.get_id() + ' ' + cpp_compiler.version() + ') with required C++ standard (C++23)') endif -GIT_BRANCH = run_command('git', 'rev-parse', '--abbrev-ref', 'HEAD', check: false).stdout().strip() -GIT_COMMIT_HASH = run_command('git', 'rev-parse', 'HEAD', check: false).stdout().strip() -GIT_COMMIT_MESSAGE = run_command('sh', '-c', 'git show | head -n 5 | tail -n 1', check: false).stdout().strip() -GIT_DIRTY = run_command('sh', '-c', 'git diff-index --quiet HEAD -- || echo "dirty"', check: false).stdout().strip() - add_project_arguments( [ '-Wno-unused-parameter', '-Wno-unused-value', '-Wno-missing-field-initializers', '-Wno-narrowing', - - f'-DGIT_BRANCH="@GIT_BRANCH@"', - f'-DGIT_COMMIT_HASH="@GIT_COMMIT_HASH@"', - f'-DGIT_COMMIT_MESSAGE="@GIT_COMMIT_MESSAGE@"', - f'-DGIT_DIRTY="@GIT_DIRTY@"', ], language: 'cpp') @@ -81,6 +71,8 @@ foreach file : headers install_headers(file, subdir: 'hyprland', preserve_path: true) endforeach +version_h = run_command('sh', '-c', 'scripts/generateVersion.sh') + subdir('protocols') subdir('src') subdir('hyprctl') diff --git a/nix/default.nix b/nix/default.nix index 96fa12d7..d12bc073 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -105,9 +105,15 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov postPatch = '' # Fix hardcoded paths to /usr installation sed -i "s#/usr#$out#" src/render/OpenGL.cpp - substituteInPlace meson.build \ - --replace "@GIT_COMMIT_HASH@" '${commit}' \ - --replace "@GIT_DIRTY@" '${ + + # Generate version.h + cp src/version.h.in src/version.h + substituteInPlace src/version.h \ + --replace "@HASH@" '${commit}' \ + --replace "@BRANCH@" "" \ + --replace "@MESSAGE@" "" \ + --replace "@TAG@" "" \ + --replace "@DIRTY@" '${ if commit == "" then "dirty" else "" diff --git a/nix/patches/meson-build.patch b/nix/patches/meson-build.patch index d0cba18a..23442172 100644 --- a/nix/patches/meson-build.patch +++ b/nix/patches/meson-build.patch @@ -1,20 +1,8 @@ diff --git a/meson.build b/meson.build -index f3802553..6a924a79 100644 +index 726933bc..28b4d9ac 100644 --- a/meson.build +++ b/meson.build -@@ -21,9 +21,9 @@ else - endif - - GIT_BRANCH = run_command('git', 'rev-parse', '--abbrev-ref', 'HEAD', check: false).stdout().strip() --GIT_COMMIT_HASH = run_command('git', 'rev-parse', 'HEAD', check: false).stdout().strip() -+GIT_COMMIT_HASH = '@GIT_COMMIT_HASH@' - GIT_COMMIT_MESSAGE = run_command('sh', '-c', 'git show | head -n 5 | tail -n 1', check: false).stdout().strip() --GIT_DIRTY = run_command('sh', '-c', 'git diff-index --quiet HEAD -- || echo "dirty"', check: false).stdout().strip() -+GIT_DIRTY = '@GIT_DIRTY@' - - add_project_arguments( - [ -@@ -39,21 +39,8 @@ add_project_arguments( +@@ -29,20 +29,7 @@ add_project_arguments( ], language: 'cpp') @@ -32,17 +20,24 @@ index f3802553..6a924a79 100644 -have_xwayland = xcb_dep.found() and have_xwlr - -if not have_xwayland -- add_project_arguments('-DNO_XWAYLAND', language: 'cpp') +if get_option('xwayland').disabled() -+ add_project_arguments('-DNO_XWAYLAND', language: 'cpp') + add_project_arguments('-DNO_XWAYLAND', language: 'cpp') endif - backtrace_dep = cpp_compiler.find_library('execinfo', required: false) +@@ -71,8 +58,6 @@ foreach file : headers + install_headers(file, subdir: 'hyprland', preserve_path: true) + endforeach + +-version_h = run_command('sh', '-c', 'scripts/generateVersion.sh') +- + subdir('protocols') + subdir('src') + subdir('hyprctl') diff --git a/src/meson.build b/src/meson.build -index 7b658d31..60aa4057 100644 +index 2065c6f5..55530605 100644 --- a/src/meson.build +++ b/src/meson.build -@@ -7,16 +7,16 @@ executable('Hyprland', src, +@@ -9,16 +9,16 @@ executable('Hyprland', src, server_protos, dependency('wayland-server'), dependency('wayland-client'), diff --git a/scripts/generateVersion.sh b/scripts/generateVersion.sh new file mode 100755 index 00000000..01bf1539 --- /dev/null +++ b/scripts/generateVersion.sh @@ -0,0 +1,14 @@ +#!/bin/sh +cp ./src/version.h.in ./src/version.h -fr + +HASH=$(git rev-parse HEAD) +BRANCH=$(git rev-parse --abbrev-ref HEAD) +MESSAGE=$(git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1 | sed -e 's/#//g' -e 's/\"//g') +DIRTY=$(git diff-index --quiet HEAD -- || echo \"dirty\") +TAG=$(git describe --tags) + +awk -i inplace "{sub(/@HASH@/,\"${HASH}\")}1" ./src/version.h +awk -i inplace "{sub(/@BRANCH@/,\"${BRANCH}\")}1" ./src/version.h +awk -i inplace "{sub(/@MESSAGE@/,\"${MESSAGE}\")}1" ./src/version.h +awk -i inplace "{sub(/@DIRTY@/,\"${DIRTY}\")}1" ./src/version.h +awk -i inplace "{sub(/@TAG@/,\"${TAG}\")}1" ./src/version.h \ No newline at end of file diff --git a/src/macros.hpp b/src/macros.hpp index 8874ad3e..eada3a9f 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -14,22 +14,7 @@ #define ISDEBUG false #endif -// git stuff -#ifndef GIT_COMMIT_HASH -#define GIT_COMMIT_HASH "?" -#endif -#ifndef GIT_BRANCH -#define GIT_BRANCH "?" -#endif -#ifndef GIT_COMMIT_MESSAGE -#define GIT_COMMIT_MESSAGE "?" -#endif -#ifndef GIT_DIRTY -#define GIT_DIRTY "?" -#endif -#ifndef GIT_TAG -#define GIT_TAG "?" -#endif +#include "version.h" #define SPECIAL_WORKSPACE_START (-99) @@ -57,7 +42,7 @@ if (!(expr)) { \ Debug::log(CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n{}\n\nat: line {} in {}", \ std::format(reason, ##__VA_ARGS__), __LINE__, \ - ([]() constexpr -> std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })()); \ + ([]() constexpr->std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })()); \ printf("Assertion failed! See the log in /tmp/hypr/hyprland.log for more info."); \ raise(SIGABRT); \ } @@ -76,7 +61,9 @@ } #define FORMAT_FLAG(spec__, flag__) \ - case spec__: (flag__) = true; break; + case spec__: \ + (flag__) = true; \ + break; #define FORMAT_NUMBER(buf__) \ case '0': \ @@ -88,7 +75,9 @@ case '6': \ case '7': \ case '8': \ - case '9': (buf__).push_back(*it); break; + case '9': \ + (buf__).push_back(*it); \ + break; #if ISDEBUG #define UNREACHABLE() \ diff --git a/src/version.h.in b/src/version.h.in new file mode 100644 index 00000000..01cfa7c5 --- /dev/null +++ b/src/version.h.in @@ -0,0 +1,5 @@ +#define GIT_COMMIT_HASH "@HASH@" +#define GIT_BRANCH "@BRANCH@" +#define GIT_COMMIT_MESSAGE "@MESSAGE@" +#define GIT_DIRTY "@DIRTY@" +#define GIT_TAG "@TAG@" \ No newline at end of file From a0038fa161f48f779c38e297bb71335040375b9f Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Tue, 10 Oct 2023 22:53:23 +0300 Subject: [PATCH 067/513] CI/release: update version generation --- .github/workflows/release.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 2c1517c1..cbf99a02 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -15,10 +15,15 @@ jobs: with: submodules: recursive + - name: Generate version + id: genversion + run: | + bash -c scripts/generateVersion.sh + mv scripts/generateVersion.sh scripts/generateVersion.sh.bak + - name: Create tarball with submodules id: tar run: | - sed -i "1s/^/#define GIT_COMMIT_HASH \"$(git rev-parse HEAD)\"\n#define GIT_TAG \"$(git describe --tags)\"\n/" ./src/macros.hpp mkdir hyprland-source; mv ./* ./hyprland-source || tar -czv --owner=0 --group=0 --no-same-owner --no-same-permissions -f source.tar.gz * - id: whatrelease From d83357f4976a240a4418a1a0a16641518a47da25 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Tue, 10 Oct 2023 21:03:03 +0100 Subject: [PATCH 068/513] internal: use pragma once in version.h --- src/version.h.in | 1 + 1 file changed, 1 insertion(+) diff --git a/src/version.h.in b/src/version.h.in index 01cfa7c5..6bfd14e5 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -1,3 +1,4 @@ +#pragma once #define GIT_COMMIT_HASH "@HASH@" #define GIT_BRANCH "@BRANCH@" #define GIT_COMMIT_MESSAGE "@MESSAGE@" From 34455844e9ac623e68375bb007535cdf979f2a02 Mon Sep 17 00:00:00 2001 From: memchr <118117622+memchr@users.noreply.github.com> Date: Wed, 11 Oct 2023 10:13:12 +0000 Subject: [PATCH 069/513] groups: ensure consistency in dispatcher behavior with global group lock (#3531) --- src/managers/KeybindManager.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 52581b62..fd298d34 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2019,7 +2019,10 @@ void CKeybindManager::moveWindowOutOfGroup(CWindow* pWindow, const std::string& void CKeybindManager::moveIntoGroup(std::string args) { char arg = args[0]; - static auto* const BIGNOREGROUPLOCK = &g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock")->intValue; + static auto* const PIGNOREGROUPLOCK = &g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock")->intValue; + + if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) + return; if (!isDirection(args)) { Debug::log(ERR, "Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg); @@ -2037,13 +2040,18 @@ void CKeybindManager::moveIntoGroup(std::string args) { return; // Do not move window into locked group if binds:ignore_group_lock is false - if (!*BIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_sGroupData.locked || (PWINDOW->m_sGroupData.pNextWindow && PWINDOW->getGroupHead()->m_sGroupData.locked))) + if (!*PIGNOREGROUPLOCK && (PWINDOWINDIR->getGroupHead()->m_sGroupData.locked || (PWINDOW->m_sGroupData.pNextWindow && PWINDOW->getGroupHead()->m_sGroupData.locked))) return; moveWindowIntoGroup(PWINDOW, PWINDOWINDIR); } void CKeybindManager::moveOutOfGroup(std::string args) { + static auto* const PIGNOREGROUPLOCK = &g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock")->intValue; + + if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) + return; + const auto PWINDOW = g_pCompositor->m_pLastWindow; if (!PWINDOW || !PWINDOW->m_sGroupData.pNextWindow) @@ -2065,6 +2073,12 @@ void CKeybindManager::moveWindowOrGroup(std::string args) { const auto PWINDOW = g_pCompositor->m_pLastWindow; if (!PWINDOW || PWINDOW->m_bIsFullscreen) return; + + if (!*PIGNOREGROUPLOCK && g_pKeybindManager->m_bGroupsLocked) { + g_pLayoutManager->getCurrentLayout()->moveWindowTo(PWINDOW, args); + return; + } + const auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, arg); const bool ISWINDOWGROUP = PWINDOW->m_sGroupData.pNextWindow; From 0cf3d5b39a04dd7690dd6bda33fb4bd1194437d9 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Wed, 11 Oct 2023 18:38:34 +0000 Subject: [PATCH 070/513] build: Unbreak Meson build on FreeBSD (#3549) * generateVersion.sh: move cp(1) flags before arguments POSIX and BSD cp(1) don't support flags after arguments e.g., cp: -fr is not a directory * generateVersion.sh: switch to sed(1) -i for better compatibility On BSDs awk is usually The One True Awk thus doesn't support `-i inplace`. awk: unknown option -i ignored awk: can't open file {sub(/@HASH@/,"1234567890abcdef")}1 source line number 1 --- scripts/generateVersion.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/generateVersion.sh b/scripts/generateVersion.sh index 01bf1539..c54e2ebd 100755 --- a/scripts/generateVersion.sh +++ b/scripts/generateVersion.sh @@ -1,14 +1,14 @@ #!/bin/sh -cp ./src/version.h.in ./src/version.h -fr +cp -fr ./src/version.h.in ./src/version.h HASH=$(git rev-parse HEAD) BRANCH=$(git rev-parse --abbrev-ref HEAD) MESSAGE=$(git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1 | sed -e 's/#//g' -e 's/\"//g') -DIRTY=$(git diff-index --quiet HEAD -- || echo \"dirty\") +DIRTY=$(git diff-index --quiet HEAD -- || echo dirty) TAG=$(git describe --tags) -awk -i inplace "{sub(/@HASH@/,\"${HASH}\")}1" ./src/version.h -awk -i inplace "{sub(/@BRANCH@/,\"${BRANCH}\")}1" ./src/version.h -awk -i inplace "{sub(/@MESSAGE@/,\"${MESSAGE}\")}1" ./src/version.h -awk -i inplace "{sub(/@DIRTY@/,\"${DIRTY}\")}1" ./src/version.h -awk -i inplace "{sub(/@TAG@/,\"${TAG}\")}1" ./src/version.h \ No newline at end of file +sed -i -e "s#@HASH@#${HASH}#" ./src/version.h +sed -i -e "s#@BRANCH@#${BRANCH}#" ./src/version.h +sed -i -e "s#@MESSAGE@#${MESSAGE}#" ./src/version.h +sed -i -e "s#@DIRTY@#${DIRTY}#" ./src/version.h +sed -i -e "s#@TAG@#${TAG}#" ./src/version.h \ No newline at end of file From 5dc7161b1da7c9ad97122458c94c833b69eb5769 Mon Sep 17 00:00:00 2001 From: "Bernhard M. Wiedemann" Date: Wed, 11 Oct 2023 20:49:42 +0200 Subject: [PATCH 071/513] meson: Sort input file list (#3550) so that hyprland builds in a reproducible way in spite of non-deterministic filesystem readdir order. See https://reproducible-builds.org/ for why this is good. This patch was done while working on reproducible builds for openSUSE. Co-authored-by: Bernhard M. Wiedemann --- src/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/meson.build b/src/meson.build index 2065c6f5..0af864b9 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,4 +1,4 @@ -globber = run_command('find', '.', '-name', '*.cpp', check: true) +globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true) src = globber.stdout().strip().split('\n') executable('Hyprland', src, From 06cc42441cd5b24444f7c79495851dedde8bc732 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Wed, 11 Oct 2023 22:27:53 +0100 Subject: [PATCH 072/513] build: guard execinfo.h via build systems (#3547) * guard execinfo via cmake * libexecinfo -> execinfo macro name * meson: add execinfo check * move check in cmake up --------- Co-authored-by: Mihai Fufezan --- CMakeLists.txt | 6 ++++++ meson.build | 4 ++++ src/debug/CrashReporter.cpp | 27 +++++++++++++-------------- src/helpers/MiscFunctions.cpp | 12 +++++++++--- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 29eccd64..b67314bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,6 +97,12 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) add_link_options(-pg -no-pie -fno-builtin) endif() +check_include_file("execinfo.h" EXECINFOH) +if(EXECINFOH) + message(STATUS "Configuration supports execinfo") + add_compile_definitions(HAS_EXECINFO) +endif() + include(CheckLibraryExists) check_library_exists(execinfo backtrace "" HAVE_LIBEXECINFO) if(HAVE_LIBEXECINFO) diff --git a/meson.build b/meson.build index 726933bc..1d2c7f9f 100644 --- a/meson.build +++ b/meson.build @@ -29,6 +29,10 @@ add_project_arguments( ], language: 'cpp') +if cpp_compiler.check_header('execinfo.h') + add_project_arguments('-DHAS_EXECINFO', language: 'cpp') +endif + wlroots = subproject('wlroots', default_options: ['examples=false', 'renderers=gles2']) have_xwlr = wlroots.get_variable('features').get('xwayland') xcb_dep = dependency('xcb', required: get_option('xwayland')) diff --git a/src/debug/CrashReporter.cpp b/src/debug/CrashReporter.cpp index 1a28a780..ddc52561 100644 --- a/src/debug/CrashReporter.cpp +++ b/src/debug/CrashReporter.cpp @@ -1,7 +1,6 @@ #include "CrashReporter.hpp" #include #include -#include #include #include @@ -14,19 +13,19 @@ std::string getRandomMessage() { const std::vector MESSAGES = {"Sorry, didn't mean to...", - "This was an accident, I swear!", - "Calm down, it was a misinput! MISINPUT!", - "Oops", - "Vaxry is going to be upset.", - "Who tried dividing by zero?!", - "Maybe you should try dusting your PC in the meantime?", - "I tried so hard, and got so far...", - "I don't feel so good...", - "*thud*", - "Well this is awkward.", - "\"stable\"", - "I hope you didn't have any unsaved progress.", - "All these computers..."}; + "This was an accident, I swear!", + "Calm down, it was a misinput! MISINPUT!", + "Oops", + "Vaxry is going to be upset.", + "Who tried dividing by zero?!", + "Maybe you should try dusting your PC in the meantime?", + "I tried so hard, and got so far...", + "I don't feel so good...", + "*thud*", + "Well this is awkward.", + "\"stable\"", + "I hope you didn't have any unsaved progress.", + "All these computers..."}; std::random_device dev; std::mt19937 engine(dev()); diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index e54e93ac..47c1180a 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -6,7 +6,9 @@ #include #include #include +#ifdef HAS_EXECINFO #include +#endif #if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include @@ -689,9 +691,10 @@ std::string replaceInString(std::string subject, const std::string& search, cons std::vector getBacktrace() { std::vector callstack; - void* bt[1024]; - size_t btSize; - char** btSymbols; +#ifdef HAS_EXECINFO + void* bt[1024]; + size_t btSize; + char** btSymbols; btSize = backtrace(bt, 1024); btSymbols = backtrace_symbols(bt, btSize); @@ -699,6 +702,9 @@ std::vector getBacktrace() { for (size_t i = 0; i < btSize; ++i) { callstack.emplace_back(SCallstackFrameInfo{bt[i], std::string{btSymbols[i]}}); } +#else + callstack.emplace_back(SCallstackFrameInfo{nullptr, "configuration does not support execinfo.h"}); +#endif return callstack; } From e4bcd2e2da3136fb55886c4f02dd4a01099e687b Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Thu, 12 Oct 2023 17:26:31 +0100 Subject: [PATCH 073/513] monitor: ensure vrr on workspace change --- src/helpers/Monitor.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 25a17189..e96da35c 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -554,6 +554,8 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool g_pHyprRenderer->damageMonitor(this); g_pCompositor->updateFullscreenFadeOnWorkspace(pWorkspace); + + g_pConfigManager->ensureVRR(this); } void CMonitor::changeWorkspace(const int& id, bool internal) { From 3a61350286de842c7f1566c38e2b42821080ddf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Lewandowski?= <49685661+FakeMichau@users.noreply.github.com> Date: Fri, 13 Oct 2023 01:05:05 +0200 Subject: [PATCH 074/513] notifications: Schedule a frame on notification creation (#3556) --- src/debug/HyprNotificationOverlay.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index b19f56fa..b4ed38c3 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -44,6 +44,10 @@ void CHyprNotificationOverlay::addNotification(const std::string& text, const CC PNOTIF->started.reset(); PNOTIF->timeMs = timeMs; PNOTIF->icon = icon; + + for (auto& m : g_pCompositor->m_vMonitors) { + g_pCompositor->scheduleFrameForMonitor(m.get()); + } } wlr_box CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) { From 424c9a7e704590db5c823557e5e388e366f7b1cd Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 13 Oct 2023 22:11:08 +0100 Subject: [PATCH 075/513] render: stop locking SWC on tearing --- src/render/Renderer.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index efdf3ce6..c4daa416 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -880,10 +880,6 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { if (pMonitor->tearingState.activelyTearing != shouldTear) { // change of state pMonitor->tearingState.activelyTearing = shouldTear; - - for (auto& m : g_pCompositor->m_vMonitors) { - wlr_output_lock_software_cursors(m->output, pMonitor->tearingState.activelyTearing); - } } EMIT_HOOK_EVENT("preRender", pMonitor); From d5a572bd39e5b29af8a17af792a43b409ae1cb06 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sat, 14 Oct 2023 18:47:43 +0100 Subject: [PATCH 076/513] Plugin API: Add version query (#3545) --- src/plugins/PluginAPI.cpp | 11 ++++++++++- src/plugins/PluginAPI.hpp | 26 +++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/plugins/PluginAPI.cpp b/src/plugins/PluginAPI.cpp index f79af312..ae289396 100644 --- a/src/plugins/PluginAPI.cpp +++ b/src/plugins/PluginAPI.cpp @@ -277,7 +277,7 @@ APICALL std::vector HyprlandAPI::findFunctionsByName(HANDLE hand const auto FPATH = std::filesystem::canonical(exe); #elif defined(__OpenBSD__) // Neither KERN_PROC_PATHNAME nor /proc are supported - const auto FPATH = std::filesystem::canonical("/usr/local/bin/Hyprland"); + const auto FPATH = std::filesystem::canonical("/usr/local/bin/Hyprland"); #else const auto FPATH = std::filesystem::canonical("/proc/self/exe"); #endif @@ -338,3 +338,12 @@ APICALL std::vector HyprlandAPI::findFunctionsByName(HANDLE hand return matches; } + +APICALL SVersionInfo HyprlandAPI::getHyprlandVersion(HANDLE handle) { + auto* const PLUGIN = g_pPluginSystem->getPluginByHandle(handle); + + if (!PLUGIN) + return {}; + + return {GIT_COMMIT_HASH, GIT_TAG, GIT_DIRTY != std::string(""), GIT_BRANCH, GIT_COMMIT_MESSAGE}; +} \ No newline at end of file diff --git a/src/plugins/PluginAPI.hpp b/src/plugins/PluginAPI.hpp index c14c820a..2809c3f6 100644 --- a/src/plugins/PluginAPI.hpp +++ b/src/plugins/PluginAPI.hpp @@ -42,6 +42,14 @@ struct SFunctionMatch { std::string demangled; }; +struct SVersionInfo { + std::string hash; + std::string tag; + bool dirty = false; + std::string branch; + std::string message; +}; + #define APICALL extern "C" #define EXPORT __attribute__((visibility("default"))) #define REQUIRED @@ -250,4 +258,20 @@ namespace HyprlandAPI { Empty means either none found or handle was invalid */ APICALL std::vector findFunctionsByName(HANDLE handle, const std::string& name); -}; \ No newline at end of file + + /* + Returns the hyprland version data. It's highly advised to not run plugins compiled + for a different hash. + */ + APICALL SVersionInfo getHyprlandVersion(HANDLE handle); +}; + +/* + Get the hash this plugin/server was compiled with. + + This function will end up in both hyprland and any/all plugins, + and can be found by a simple dlsym() +*/ +APICALL inline EXPORT const char* __hyprland_api_get_hash() { + return GIT_COMMIT_HASH; +} From d4e4931008cc64e5b94a65c5e692ff9ed459280b Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sat, 14 Oct 2023 18:48:05 +0100 Subject: [PATCH 077/513] build: CMake pipeline improvements (#3564) --- .github/workflows/ci.yaml | 4 +- CMakeLists.txt | 27 ++++++++++++- Makefile | 83 ++++++--------------------------------- hyprctl/CMakeLists.txt | 8 ++++ 4 files changed, 47 insertions(+), 75 deletions(-) mode change 100644 => 100755 CMakeLists.txt create mode 100644 hyprctl/CMakeLists.txt diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 2c9b60a6..b8093491 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -39,7 +39,7 @@ jobs: mkdir hyprland/assets cp ./LICENSE hyprland/ cp build/Hyprland hyprland/ - cp hyprctl/hyprctl hyprland/ + cp build/hyprctl/hyprctl hyprland/ cp subprojects/wlroots/build/libwlroots.so.12032 hyprland/ cp build/Hyprland hyprland/ cp -r example/ hyprland/ @@ -105,4 +105,4 @@ jobs: - name: Configure run: mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DNO_XWAYLAND:STRING=true -H./ -B./build -G Ninja - name: Compile - run: make config && make release + run: make release diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100644 new mode 100755 index b67314bc..04008a8b --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,27 @@ execute_process( # # +# udis +add_subdirectory("subprojects/udis86") + +# wlroots +message(STATUS "Setting up wlroots") + +include(ExternalProject) +string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER) +ExternalProject_Add( + wlroots + PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots + SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots + PATCH_COMMAND sed -E -i -e "s/(soversion = 12)([^032]|$$)/soversion = 12032/g" meson.build + CONFIGURE_COMMAND meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $,-Db_sanitize=address,-Db_sanitize=none> && meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $,-Db_sanitize=address,-Db_sanitize=none> --reconfigure + BUILD_COMMAND ninja -C build + BUILD_ALWAYS true + BUILD_IN_SOURCE true + BUILD_BYPRODUCTS ${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.12032 + INSTALL_COMMAND echo "wlroots: install not needed" +) + find_program(WaylandScanner NAMES wayland-scanner) message(STATUS "Found WaylandScanner at ${WaylandScanner}") execute_process( @@ -67,6 +88,7 @@ pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wa file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp") add_executable(Hyprland ${SRCFILES}) +add_dependencies(Hyprland wlroots) if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) message(STATUS "Setting debug flags") @@ -182,7 +204,7 @@ target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads - ${CMAKE_SOURCE_DIR}/subprojects/udis86/build/libudis86/liblibudis86.a + libudis86 ) protocol("protocols/idle.xml" "idle" true) @@ -201,3 +223,6 @@ protocol("staging/fractional-scale/fractional-scale-v1.xml" "fractional-scale-v1 protocol("staging/tearing-control/tearing-control-v1.xml" "tearing-control-v1" false) protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v1" false) protocol("staging/cursor-shape/cursor-shape-v1.xml" "cursor-shape-v1" false) + +# hyprctl +add_subdirectory(hyprctl) \ No newline at end of file diff --git a/Makefile b/Makefile index 6a96015c..cd39adb8 100644 --- a/Makefile +++ b/Makefile @@ -23,32 +23,20 @@ debug: clear: rm -rf build rm -f ./protocols/*-protocol.h ./protocols/*-protocol.c - rm -f ./hyprctl/hyprctl rm -rf ./subprojects/wlroots/build all: + @if [[ "$EUID" = 0 ]]; then echo -en "Avoid running $(MAKE) all as sudo.\n"; fi $(MAKE) clear - $(MAKE) fixwlr - cd ./subprojects/wlroots && meson setup build/ --buildtype=release && ninja -C build/ && mkdir -p ${PREFIX}/lib/ && cp ./build/libwlroots.so.12032 ${PREFIX}/lib/ || echo "Could not install libwlroots to ${PREFIX}/lib/libwlroots.so.12032" - cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B./build -G Ninja && cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` $(MAKE) release - $(MAKE) -C hyprctl all install: - $(MAKE) clear - $(MAKE) fixwlr - cd ./subprojects/wlroots && meson setup build/ --buildtype=release && ninja -C build/ && mkdir -p ${PREFIX}/lib/ && cp ./build/libwlroots.so.12032 ${PREFIX}/lib/ || echo "Could not install libwlroots to ${PREFIX}/lib/libwlroots.so.12032" - cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B./build -G Ninja && cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` && cd ../.. - chmod -R 777 subprojects/udis86 - chmod -R 777 subprojects/wlroots - $(MAKE) release - $(MAKE) -C hyprctl all - chmod 755 ./hyprctl/hyprctl + @if [ ! -d ./build/Hyprland ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi mkdir -p ${PREFIX}/share/wayland-sessions mkdir -p ${PREFIX}/bin cp -f ./build/Hyprland ${PREFIX}/bin - cp -f ./hyprctl/hyprctl ${PREFIX}/bin + cp -f ./build/hyprctl/hyprctl ${PREFIX}/bin chmod 755 ${PREFIX}/bin/Hyprland chmod 755 ${PREFIX}/bin/hyprctl if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi @@ -58,26 +46,10 @@ install: mkdir -p ${PREFIX}/share/man/man1 install -m644 ./docs/*.1 ${PREFIX}/share/man/man1 - mkdir -p ${PREFIX}/include/hyprland - mkdir -p ${PREFIX}/include/hyprland/protocols - mkdir -p ${PREFIX}/include/hyprland/wlroots - mkdir -p ${PREFIX}/share/pkgconfig - mkdir -p ${PREFIX}/share/xdg-desktop-portal - - find src -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland - cd subprojects/wlroots/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlroots && cd ../../.. - cd subprojects/wlroots/build/include && find . -name '*.h*' -print0 | cpio --quiet -0dump ${PREFIX}/include/hyprland/wlroots && cd ../../../.. - cp ./protocols/*-protocol.h ${PREFIX}/include/hyprland/protocols - cp ./build/hyprland.pc ${PREFIX}/share/pkgconfig - cp ./assets/hyprland-portals.conf ${PREFIX}/share/xdg-desktop-portal/ - if [ -d /usr/share/pkgconfig ]; then cp ./build/hyprland.pc /usr/share/pkgconfig 2>/dev/null || true; fi + mkdir -p ${PREFIX}/lib/ + cp ./subprojects/wlroots/build/libwlroots.so.12032 ${PREFIX}/lib/ - chmod -R 755 ${PREFIX}/include/hyprland - chmod 755 ${PREFIX}/share/pkgconfig - -cleaninstall: - echo -en "$(MAKE) cleaninstall has been DEPRECATED, you should avoid using it in the future.\nRunning $(MAKE) install instead...\n" - $(MAKE) install + $(MAKE) installheaders uninstall: rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop @@ -88,37 +60,12 @@ uninstall: rm -f ${PREFIX}/share/man/man1/Hyprland.1 rm -f ${PREFIX}/share/man/man1/hyprctl.1 -fixwlr: - sed -E -i -e 's/(soversion = 12)([^032]|$$)/soversion = 12032/g' subprojects/wlroots/meson.build - - rm -rf ./subprojects/wlroots/build - -config: - $(MAKE) fixwlr - - meson setup subprojects/wlroots/build subprojects/wlroots --prefix=${PREFIX} --buildtype=release -Dwerror=false -Dexamples=false -Drenderers="gles2" - ninja -C subprojects/wlroots/build/ - - ninja -C subprojects/wlroots/build/ install - - chmod -R 777 subprojects/wlroots - - cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja && cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` - - chmod -R 777 subprojects/udis86 - pluginenv: - cd subprojects/udis86 && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja && cmake --build ./build --config Release --target all -j`nproc 2>/dev/null || getconf NPROCESSORS_CONF` - - $(MAKE) fixwlr - - meson setup subprojects/wlroots/build subprojects/wlroots --prefix=${PREFIX} --buildtype=release -Dwerror=false -Dexamples=false - ninja -C subprojects/wlroots/build/ - - chmod -R 777 subprojects/udis86 - chmod -R 777 subprojects/wlroots - - cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja + @echo -en "$(MAKE) pluginenv has been deprecated.\nPlease run $(MAKE) all && sudo $(MAKE) installheaders\n" + @exit 1 + +installheaders: + @if [ ! -d ./build/Hyprland ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi mkdir -p ${PREFIX}/include/hyprland mkdir -p ${PREFIX}/include/hyprland/protocols @@ -135,14 +82,6 @@ pluginenv: chmod -R 755 ${PREFIX}/include/hyprland chmod 755 ${PREFIX}/share/pkgconfig -configdebug: - $(MAKE) fixwlr - - meson setup subprojects/wlroots/build subprojects/wlroots --prefix=${PREFIX} --buildtype=debug -Dwerror=false -Dexamples=false -Drenderers="gles2" -Db_sanitize=address - ninja -C subprojects/wlroots/build/ - - ninja -C subprojects/wlroots/build/ install - man: pandoc ./docs/Hyprland.1.rst \ --standalone \ diff --git a/hyprctl/CMakeLists.txt b/hyprctl/CMakeLists.txt new file mode 100644 index 00000000..99964b50 --- /dev/null +++ b/hyprctl/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.19) + +project( + hyprctl + DESCRIPTION "Control utility for Hyprland" +) + +add_executable(hyprctl "main.cpp") \ No newline at end of file From 21b5cf402afb8a72ffbf12efdd0a0d46849d86dd Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 14 Oct 2023 18:58:23 +0100 Subject: [PATCH 078/513] makefile: warn users when doing sudo make install --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index cd39adb8..095c699c 100644 --- a/Makefile +++ b/Makefile @@ -32,6 +32,7 @@ all: install: @if [ ! -d ./build/Hyprland ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi + @echo -en "!NOTE: Please note make install does not compile Hyprland and only installs the already built files." mkdir -p ${PREFIX}/share/wayland-sessions mkdir -p ${PREFIX}/bin From 962a0de01ad4d8f9f84a2283c2c3c749395d450d Mon Sep 17 00:00:00 2001 From: memchr <118117622+memchr@users.noreply.github.com> Date: Sat, 14 Oct 2023 19:59:11 +0000 Subject: [PATCH 079/513] meson: use `ln` with force flag (#3568) --- subprojects/packagefiles/wlroots-meson-build.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/packagefiles/wlroots-meson-build.patch b/subprojects/packagefiles/wlroots-meson-build.patch index 5e7565a3..6741fdc7 100644 --- a/subprojects/packagefiles/wlroots-meson-build.patch +++ b/subprojects/packagefiles/wlroots-meson-build.patch @@ -4,7 +4,7 @@ index e669800..687786b 100644 +++ b/include/meson.build @@ -1,4 +1,5 @@ -subdir('wlr') -+run_command('ln', '-s', join_paths(meson.project_source_root(), 'include', 'wlr'), join_paths(meson.project_source_root(), 'include', 'wlroots'), check: true) ++run_command('ln', '-sf', join_paths(meson.project_source_root(), 'include', 'wlr'), join_paths(meson.project_source_root(), 'include', 'wlroots'), check: true) +subdir('wlroots') exclude_files = ['meson.build', 'config.h.in', 'version.h.in'] From 261c594458fec8bc64136eebf7c7e4e5ab421907 Mon Sep 17 00:00:00 2001 From: Ali Rizvi <31909298+Frontear@users.noreply.github.com> Date: Sat, 14 Oct 2023 17:30:17 -0400 Subject: [PATCH 080/513] makefile: fix using `-d` test for a binary file AND re-add missing portals conf (#3570) * fix: Makefile test modified: src/Makefile * add: hyprland-portals.conf cp to Makefile modified: src/Makefile --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 095c699c..dc7f7329 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ all: $(MAKE) release install: - @if [ ! -d ./build/Hyprland ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi + @if [ ! -f ./build/Hyprland ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi @echo -en "!NOTE: Please note make install does not compile Hyprland and only installs the already built files." mkdir -p ${PREFIX}/share/wayland-sessions @@ -43,6 +43,8 @@ install: if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi mkdir -p ${PREFIX}/share/hyprland cp ./assets/wall_* ${PREFIX}/share/hyprland + mkdir -p ${PREFIX}/share/xdg-desktop-portal + cp ./assets/hyprland-portals.conf ${PREFIX}/share/xdg-desktop-portal mkdir -p ${PREFIX}/share/man/man1 install -m644 ./docs/*.1 ${PREFIX}/share/man/man1 @@ -66,7 +68,7 @@ pluginenv: @exit 1 installheaders: - @if [ ! -d ./build/Hyprland ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi + @if [ ! -f ./build/Hyprland ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi mkdir -p ${PREFIX}/include/hyprland mkdir -p ${PREFIX}/include/hyprland/protocols From 43b39e0bc6a83ce190ff09054beb713e0431f19b Mon Sep 17 00:00:00 2001 From: memchr <118117622+memchr@users.noreply.github.com> Date: Sun, 15 Oct 2023 11:22:51 +0000 Subject: [PATCH 081/513] build: include version.h in PluginAPI.hpp (#3571) --- src/plugins/PluginAPI.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/PluginAPI.hpp b/src/plugins/PluginAPI.hpp index 2809c3f6..a406f2e6 100644 --- a/src/plugins/PluginAPI.hpp +++ b/src/plugins/PluginAPI.hpp @@ -23,6 +23,7 @@ Feel like the API is missing something you'd like to use in your plugin? Open an #include "../helpers/Color.hpp" #include "HookSystem.hpp" #include "../SharedDefs.hpp" +#include "../version.h" #include #include From 442209942fdedbdded6362cafed736c327da0e1c Mon Sep 17 00:00:00 2001 From: Philip Damianik <39028343+pdamianik@users.noreply.github.com> Date: Sun, 15 Oct 2023 20:07:23 +0200 Subject: [PATCH 082/513] cleanup: Replace find() with C++20 starts_with(), ends_with() and contains() (#3572) * Replace find() with C++20 starts_with() and ends_with() * Replace find() with C++20 contains() --- src/Compositor.cpp | 14 +++--- src/Window.cpp | 12 ++--- src/config/ConfigManager.cpp | 74 ++++++++++++++--------------- src/debug/HyprCtl.cpp | 26 +++++----- src/events/Windows.cpp | 42 ++++++++-------- src/helpers/MiscFunctions.cpp | 28 +++++------ src/helpers/WLClasses.cpp | 4 +- src/helpers/Workspace.cpp | 4 +- src/managers/AnimationManager.cpp | 14 +++--- src/managers/KeybindManager.cpp | 12 ++--- src/managers/input/InputManager.cpp | 4 +- src/managers/input/Swipe.cpp | 4 +- src/plugins/PluginAPI.cpp | 2 +- src/render/OpenGL.cpp | 2 +- 14 files changed, 120 insertions(+), 122 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index b9be9f18..f02f7c66 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -554,7 +554,7 @@ CMonitor* CCompositor::getMonitorFromName(const std::string& name) { CMonitor* CCompositor::getMonitorFromDesc(const std::string& desc) { for (auto& m : m_vMonitors) { - if (m->output->description && std::string(m->output->description).find(desc) == 0) + if (m->output->description && std::string(m->output->description).starts_with(desc)) return m.get(); } return nullptr; @@ -1617,7 +1617,7 @@ CWorkspace* CCompositor::getWorkspaceByName(const std::string& name) { } CWorkspace* CCompositor::getWorkspaceByString(const std::string& str) { - if (str.find("name:") == 0) { + if (str.starts_with("name:")) { return getWorkspaceByName(str.substr(str.find_first_of(':') + 1)); } @@ -1976,14 +1976,14 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) { Debug::log(ERR, "Error in getMonitorFromString: invalid arg 1"); return nullptr; } - } else if (name.find("desc:") == 0) { + } else if (name.starts_with("desc:")) { const auto DESCRIPTION = name.substr(5); for (auto& m : m_vMonitors) { if (!m->output) continue; - if (m->output->description && std::string(m->output->description).find(DESCRIPTION) == 0) { + if (m->output->description && std::string(m->output->description).starts_with(DESCRIPTION)) { return m.get(); } } @@ -2245,13 +2245,13 @@ CWindow* CCompositor::getWindowByRegex(const std::string& regexp) { std::regex regexCheck(regexp); std::string matchCheck; - if (regexp.find("title:") == 0) { + if (regexp.starts_with("title:")) { mode = MODE_TITLE_REGEX; regexCheck = std::regex(regexp.substr(6)); - } else if (regexp.find("address:") == 0) { + } else if (regexp.starts_with("address:")) { mode = MODE_ADDRESS; matchCheck = regexp.substr(8); - } else if (regexp.find("pid:") == 0) { + } else if (regexp.starts_with("pid:")) { mode = MODE_PID; matchCheck = regexp.substr(4); } diff --git a/src/Window.cpp b/src/Window.cpp index 9055101e..6a83c7fa 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -499,15 +499,15 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { m_sAdditionalConfigData.forceOpaque = true; } else if (r.szRule == "immediate") { m_sAdditionalConfigData.forceTearing = true; - } else if (r.szRule.find("rounding") == 0) { + } else if (r.szRule.starts_with("rounding")) { try { m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1)); } catch (std::exception& e) { Debug::log(ERR, "Rounding rule \"{}\" failed with: {}", r.szRule, e.what()); } - } else if (r.szRule.find("bordersize") == 0) { + } else if (r.szRule.starts_with("bordersize")) { try { m_sAdditionalConfigData.borderSize = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1)); } catch (std::exception& e) { Debug::log(ERR, "Bordersize rule \"{}\" failed with: {}", r.szRule, e.what()); } - } else if (r.szRule.find("opacity") == 0) { + } else if (r.szRule.starts_with("opacity")) { try { CVarList vars(r.szRule, 0, ' '); @@ -540,10 +540,10 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { } catch (std::exception& e) { Debug::log(ERR, "Opacity rule \"{}\" failed with: {}", r.szRule, e.what()); } } else if (r.szRule == "noanim") { m_sAdditionalConfigData.forceNoAnims = true; - } else if (r.szRule.find("animation") == 0) { + } else if (r.szRule.starts_with("animation")) { auto STYLE = r.szRule.substr(r.szRule.find_first_of(' ') + 1); m_sAdditionalConfigData.animationStyle = STYLE; - } else if (r.szRule.find("bordercolor") == 0) { + } else if (r.szRule.starts_with("bordercolor")) { try { std::string colorPart = removeBeginEndSpacesTabs(r.szRule.substr(r.szRule.find_first_of(' ') + 1)); @@ -559,7 +559,7 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { m_sAdditionalConfigData.dimAround = true; } else if (r.szRule == "keepaspectratio") { m_sAdditionalConfigData.keepAspectRatio = true; - } else if (r.szRule.find("xray") == 0) { + } else if (r.szRule.starts_with("xray")) { CVarList vars(r.szRule, 0, ' '); try { diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 2d19389e..5ae341f8 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -369,8 +369,8 @@ void CConfigManager::init() { } void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::string& VALUE) { - if (configValues.find(COMMAND) == configValues.end()) { - if (COMMAND.find("device:") != 0 /* devices parsed later */ && COMMAND.find("plugin:") != 0 /* plugins parsed later */) { + if (!configValues.contains(COMMAND)) { + if (!COMMAND.starts_with("device:") /* devices parsed later */ && !COMMAND.starts_with("plugin:") /* plugins parsed later */) { if (COMMAND[0] == '$') { // register a dynamic var Debug::log(LOG, "Registered dynamic var \"{}\" -> {}", COMMAND, VALUE); @@ -387,7 +387,7 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s SConfigValue* CONFIGENTRY = nullptr; - if (COMMAND.find("device:") == 0) { + if (COMMAND.starts_with("device:")) { const auto DEVICE = COMMAND.substr(7).substr(0, COMMAND.find_last_of(':') - 7); const auto CONFIGVAR = COMMAND.substr(COMMAND.find_last_of(':') + 1); @@ -407,7 +407,7 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s } CONFIGENTRY = &it->second.at(CONFIGVAR); - } else if (COMMAND.find("plugin:") == 0) { + } else if (COMMAND.starts_with("plugin:")) { for (auto& [handle, pMap] : pluginConfigs) { auto it = std::find_if(pMap->begin(), pMap->end(), [&](const auto& other) { return other.first == COMMAND; }); if (it == pMap->end()) { @@ -645,11 +645,11 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string return; } - if (ARGS[1].find("pref") == 0) { + if (ARGS[1].starts_with("pref")) { newrule.resolution = Vector2D(); - } else if (ARGS[1].find("highrr") == 0) { + } else if (ARGS[1].starts_with("highrr")) { newrule.resolution = Vector2D(-1, -1); - } else if (ARGS[1].find("highres") == 0) { + } else if (ARGS[1].starts_with("highres")) { newrule.resolution = Vector2D(-1, -2); } else if (parseModeLine(ARGS[1], newrule.drmMode)) { newrule.resolution = Vector2D(newrule.drmMode.hdisplay, newrule.drmMode.vdisplay); @@ -662,14 +662,14 @@ void CConfigManager::handleMonitor(const std::string& command, const std::string newrule.refreshRate = stof(ARGS[1].substr(ARGS[1].find_first_of('@') + 1)); } - if (ARGS[2].find("auto") == 0) { + if (ARGS[2].starts_with("auto")) { newrule.offset = Vector2D(-INT32_MAX, -INT32_MAX); } else { newrule.offset.x = stoi(ARGS[2].substr(0, ARGS[2].find_first_of('x'))); newrule.offset.y = stoi(ARGS[2].substr(ARGS[2].find_first_of('x') + 1)); } - if (ARGS[3].find("auto") == 0) { + if (ARGS[3].starts_with("auto")) { newrule.scale = -1; } else { newrule.scale = stof(ARGS[3]); @@ -905,7 +905,7 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v if (KEY != "") { if (isNumber(KEY) && std::stoi(KEY) > 9) g_pKeybindManager->addKeybind(SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent}); - else if (KEY.find("code:") == 0 && isNumber(KEY.substr(5))) + else if (KEY.starts_with("code:") && isNumber(KEY.substr(5))) g_pKeybindManager->addKeybind( SKeybind{"", std::stoi(KEY.substr(5)), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent}); else @@ -924,17 +924,17 @@ void CConfigManager::handleUnbind(const std::string& command, const std::string& } bool windowRuleValid(const std::string& RULE) { - return !(RULE != "float" && RULE != "tile" && RULE.find("opacity") != 0 && RULE.find("move") != 0 && RULE.find("size") != 0 && RULE.find("minsize") != 0 && - RULE.find("maxsize") != 0 && RULE.find("pseudo") != 0 && RULE.find("monitor") != 0 && RULE.find("idleinhibit") != 0 && RULE != "nofocus" && RULE != "noblur" && - RULE != "noshadow" && RULE != "nodim" && RULE != "noborder" && RULE != "opaque" && RULE != "forceinput" && RULE != "fullscreen" && RULE != "nofullscreenrequest" && - RULE != "nomaximizerequest" && RULE != "fakefullscreen" && RULE != "nomaxsize" && RULE != "pin" && RULE != "noanim" && RULE != "dimaround" && RULE != "windowdance" && - RULE != "maximize" && RULE != "keepaspectratio" && RULE.find("animation") != 0 && RULE.find("rounding") != 0 && RULE.find("workspace") != 0 && - RULE.find("bordercolor") != 0 && RULE != "forcergbx" && RULE != "noinitialfocus" && RULE != "stayfocused" && RULE.find("bordersize") != 0 && RULE.find("xray") != 0 && - RULE.find("center") != 0 && RULE.find("group") != 0 && RULE != "immediate"); + return RULE == "float" || RULE == "tile" || RULE.starts_with("opacity") || RULE.starts_with("move") || RULE.starts_with("size") || RULE.starts_with("minsize") || + RULE.starts_with("maxsize") || RULE.starts_with("pseudo") || RULE.starts_with("monitor") || RULE.starts_with("idleinhibit") || RULE == "nofocus" || RULE == "noblur" || + RULE == "noshadow" || RULE == "nodim" || RULE == "noborder" || RULE == "opaque" || RULE == "forceinput" || RULE == "fullscreen" || RULE == "nofullscreenrequest" || + RULE == "nomaximizerequest" || RULE == "fakefullscreen" || RULE == "nomaxsize" || RULE == "pin" || RULE == "noanim" || RULE == "dimaround" || RULE == "windowdance" || + RULE == "maximize" || RULE == "keepaspectratio" || RULE.starts_with("animation") || RULE.starts_with("rounding") || RULE.starts_with("workspace") || + RULE.starts_with("bordercolor") || RULE == "forcergbx" || RULE == "noinitialfocus" || RULE == "stayfocused" || RULE.starts_with("bordersize") || RULE.starts_with("xray") || + RULE.starts_with("center") || RULE.starts_with("group") || RULE == "immediate"; } bool layerRuleValid(const std::string& RULE) { - return !(RULE != "noanim" && RULE != "blur" && RULE.find("ignorealpha") != 0 && RULE.find("ignorezero") != 0 && RULE.find("xray") != 0); + return RULE == "noanim" || RULE == "blur" || RULE.starts_with("ignorealpha") || RULE.starts_with("ignorezero") || RULE.starts_with("xray"); } void CConfigManager::handleWindowRule(const std::string& command, const std::string& value) { @@ -958,7 +958,7 @@ void CConfigManager::handleWindowRule(const std::string& command, const std::str return; } - if (RULE.find("size") == 0 || RULE.find("maxsize") == 0 || RULE.find("minsize") == 0) + if (RULE.starts_with("size") || RULE.starts_with("maxsize") || RULE.starts_with("minsize")) m_dWindowRules.push_front({RULE, VALUE}); else m_dWindowRules.push_back({RULE, VALUE}); @@ -1105,14 +1105,14 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s return; } - if (RULE.find("size") == 0 || RULE.find("maxsize") == 0 || RULE.find("minsize") == 0) + if (RULE.starts_with("size") || RULE.starts_with("maxsize") || RULE.starts_with("minsize")) m_dWindowRules.push_front(rule); else m_dWindowRules.push_back(rule); } void CConfigManager::updateBlurredLS(const std::string& name, const bool forceBlur) { - const bool BYADDRESS = name.find("address:") == 0; + const bool BYADDRESS = name.starts_with("address:"); std::string matchName = name; if (BYADDRESS) { @@ -1133,7 +1133,7 @@ void CConfigManager::updateBlurredLS(const std::string& name, const bool forceBl } void CConfigManager::handleBlurLS(const std::string& command, const std::string& value) { - if (value.find("remove,") == 0) { + if (value.starts_with("remove,")) { const auto TOREMOVE = removeBeginEndSpacesTabs(value.substr(7)); if (std::erase_if(m_dBlurLSNamespaces, [&](const auto& other) { return other == TOREMOVE; })) updateBlurredLS(TOREMOVE, false); @@ -1277,7 +1277,7 @@ void CConfigManager::handleSource(const std::string& command, const std::string& parseError += "Config error at line " + std::to_string(linenum) + " (" + configCurrentPath + "): Line parsing error."; } - if (parseError != "" && parseError.find("Config error at line") != 0) { + if (parseError != "" && !parseError.starts_with("Config error at line")) { parseError = "Config error at line " + std::to_string(linenum) + " (" + configCurrentPath + "): " + parseError; } @@ -1350,7 +1350,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std:: } } else if (COMMAND == "monitor") handleMonitor(COMMAND, VALUE); - else if (COMMAND.find("bind") == 0) + else if (COMMAND.starts_with("bind")) handleBind(COMMAND, VALUE); else if (COMMAND == "unbind") handleUnbind(COMMAND, VALUE); @@ -1374,9 +1374,9 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std:: handleBlurLS(COMMAND, VALUE); else if (COMMAND == "wsbind") handleBindWS(COMMAND, VALUE); - else if (COMMAND.find("env") == 0) + else if (COMMAND.starts_with("env")) handleEnv(COMMAND, VALUE); - else if (COMMAND.find("plugin") == 0) + else if (COMMAND.starts_with("plugin")) handlePlugin(COMMAND, VALUE); else { configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE); @@ -1389,7 +1389,7 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std:: // invalidate layouts if they changed if (needsLayoutRecalc) { - if (needsLayoutRecalc == 1 || COMMAND.contains("gaps_") || COMMAND.find("dwindle:") == 0 || COMMAND.find("master:") == 0) { + if (needsLayoutRecalc == 1 || COMMAND.contains("gaps_") || COMMAND.starts_with("dwindle:") || COMMAND.starts_with("master:")) { for (auto& m : g_pCompositor->m_vMonitors) g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); } @@ -1424,7 +1424,7 @@ void CConfigManager::applyUserDefinedVars(std::string& line, const size_t equals const auto STRAFTERDOLLAR = line.substr(dollarPlace + 1); bool found = false; for (auto& [var, value] : configDynamicVars) { - if (STRAFTERDOLLAR.find(var) == 0) { + if (STRAFTERDOLLAR.starts_with(var)) { line.replace(dollarPlace, var.length() + 1, value); found = true; break; @@ -1434,7 +1434,7 @@ void CConfigManager::applyUserDefinedVars(std::string& line, const size_t equals if (!found) { // maybe env? for (auto& [var, value] : environmentVariables) { - if (STRAFTERDOLLAR.find(var) == 0) { + if (STRAFTERDOLLAR.starts_with(var)) { line.replace(dollarPlace, var.length() + 1, value); break; } @@ -1600,7 +1600,7 @@ void CConfigManager::loadConfigLoadVars() { parseError += "Config error at line " + std::to_string(linenum) + " (" + mainConfigPath + "): Line parsing error."; } - if (parseError != "" && parseError.find("Config error at line") != 0) { + if (parseError != "" && !parseError.starts_with("Config error at line")) { parseError = "Config error at line " + std::to_string(linenum) + " (" + mainConfigPath + "): " + parseError; } @@ -1816,7 +1816,7 @@ SMonitorRule CConfigManager::getMonitorRuleFor(const std::string& name, const st for (auto& r : m_dMonitorRules) { if (r.name == name || - (r.name.find("desc:") == 0 && + (r.name.starts_with("desc:") && (r.name.substr(5) == displayName || r.name.substr(5) == removeBeginEndSpacesTabs(displayName.substr(0, displayName.find_first_of('(')))))) { found = &r; break; @@ -1872,7 +1872,7 @@ std::vector CConfigManager::getMatchingRules(CWindow* pWindow) { // check if we have a matching rule if (!rule.v2) { try { - if (rule.szValue.find("title:") == 0) { + if (rule.szValue.starts_with("title:")) { // we have a title rule. std::regex RULECHECK(rule.szValue.substr(6)); @@ -1930,7 +1930,7 @@ std::vector CConfigManager::getMatchingRules(CWindow* pWindow) { if (!PWORKSPACE) continue; - if (rule.szWorkspace.find("name:") == 0) { + if (rule.szWorkspace.starts_with("name:")) { if (PWORKSPACE->m_szName != rule.szWorkspace.substr(5)) continue; } else { @@ -1988,7 +1988,7 @@ std::vector CConfigManager::getMatchingRules(SLayerSurface* pLS) { return returns; for (auto& lr : m_dLayerRules) { - if (lr.targetNamespace.find("address:0x") == 0) { + if (lr.targetNamespace.starts_with("address:0x")) { if (std::format("address:0x{:x}", (uintptr_t)pLS) != lr.targetNamespace) continue; } else { @@ -2110,9 +2110,7 @@ bool CConfigManager::deviceConfigExists(const std::string& dev) { auto copy = dev; std::replace(copy.begin(), copy.end(), ' ', '-'); - const auto it = deviceConfigs.find(copy); - - return it != deviceConfigs.end(); + return deviceConfigs.contains(copy); } bool CConfigManager::shouldBlurLS(const std::string& ns) { @@ -2233,7 +2231,7 @@ CMonitor* CConfigManager::getBoundMonitorForWS(const std::string& wsname) { std::string CConfigManager::getBoundMonitorStringForWS(const std::string& wsname) { for (auto& wr : m_dWorkspaceRules) { - const auto WSNAME = wr.workspaceName.find("name:") == 0 ? wr.workspaceName.substr(5) : wr.workspaceName; + const auto WSNAME = wr.workspaceName.starts_with("name:") ? wr.workspaceName.substr(5) : wr.workspaceName; if (WSNAME == wsname) { return wr.monitor; diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index a86ac33e..a9b6a190 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -961,7 +961,7 @@ std::string dispatchSetProp(std::string request) { bool lock = false; if (vars.size() > 4) { - if (vars[4].find("lock") == 0) { + if (vars[4].starts_with("lock")) { lock = true; } } @@ -1271,7 +1271,7 @@ std::string getReply(std::string request) { return layersRequest(format); else if (request == "version") return versionRequest(format); - else if (request.find("reload") == 0) + else if (request.starts_with("reload")) return reloadRequest(request); else if (request == "devices") return devicesRequest(format); @@ -1285,27 +1285,27 @@ std::string getReply(std::string request) { return globalShortcutsRequest(format); else if (request == "animations") return animationsRequest(format); - else if (request.find("plugin") == 0) + else if (request.starts_with("plugin")) return dispatchPlugin(request); - else if (request.find("notify") == 0) + else if (request.starts_with("notify")) return dispatchNotify(request); - else if (request.find("setprop") == 0) + else if (request.starts_with("setprop")) return dispatchSetProp(request); - else if (request.find("seterror") == 0) + else if (request.starts_with("seterror")) return dispatchSeterror(request); - else if (request.find("switchxkblayout") == 0) + else if (request.starts_with("switchxkblayout")) return switchXKBLayoutRequest(request); - else if (request.find("output") == 0) + else if (request.starts_with("output")) return dispatchOutput(request); - else if (request.find("dispatch") == 0) + else if (request.starts_with("dispatch")) return dispatchRequest(request); - else if (request.find("keyword") == 0) + else if (request.starts_with("keyword")) return dispatchKeyword(request); - else if (request.find("setcursor") == 0) + else if (request.starts_with("setcursor")) return dispatchSetCursor(request); - else if (request.find("getoption") == 0) + else if (request.starts_with("getoption")) return dispatchGetOption(request, format); - else if (request.find("[[BATCH]]") == 0) + else if (request.starts_with("[[BATCH]]")) return dispatchBatch(request); return "unknown request"; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index f78a2975..84582537 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -117,7 +117,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->m_szInitialClass = g_pXWaylandManager->getAppIDClass(PWINDOW); for (auto& r : WINDOWRULES) { - if (r.szRule.find("monitor") == 0) { + if (r.szRule.starts_with("monitor")) { try { const auto MONITORSTR = removeBeginEndSpacesTabs(r.szRule.substr(r.szRule.find(' '))); @@ -151,7 +151,7 @@ void Events::listener_mapWindow(void* owner, void* data) { Debug::log(LOG, "Rule monitor, applying to {:mw}", PWINDOW); } catch (std::exception& e) { Debug::log(ERR, "Rule monitor failed, rule: {} -> {} | err: {}", r.szRule, r.szValue, e.what()); } - } else if (r.szRule.find("workspace") == 0) { + } else if (r.szRule.starts_with("workspace")) { // check if it isnt unset const auto WORKSPACERQ = r.szRule.substr(r.szRule.find_first_of(' ') + 1); @@ -167,19 +167,19 @@ void Events::listener_mapWindow(void* owner, void* data) { requestedWorkspace = ""; Debug::log(LOG, "Rule workspace matched by {}, {} applied.", PWINDOW, r.szValue); - } else if (r.szRule.find("float") == 0) { + } else if (r.szRule.starts_with("float")) { PWINDOW->m_bIsFloating = true; - } else if (r.szRule.find("tile") == 0) { + } else if (r.szRule.starts_with("tile")) { PWINDOW->m_bIsFloating = false; - } else if (r.szRule.find("pseudo") == 0) { + } else if (r.szRule.starts_with("pseudo")) { PWINDOW->m_bIsPseudotiled = true; - } else if (r.szRule.find("nofocus") == 0) { + } else if (r.szRule.starts_with("nofocus")) { PWINDOW->m_bNoFocus = true; - } else if (r.szRule.find("noinitialfocus") == 0) { + } else if (r.szRule.starts_with("noinitialfocus")) { PWINDOW->m_bNoInitialFocus = true; - } else if (r.szRule.find("nofullscreenrequest") == 0) { + } else if (r.szRule.starts_with("nofullscreenrequest")) { PWINDOW->m_bNoFullscreenRequest = true; - } else if (r.szRule.find("nomaximizerequest") == 0) { + } else if (r.szRule.starts_with("nomaximizerequest")) { PWINDOW->m_bNoMaximizeRequest = true; } else if (r.szRule == "fullscreen") { requestsFullscreen = true; @@ -199,7 +199,7 @@ void Events::listener_mapWindow(void* owner, void* data) { overridingNoMaximize = true; } else if (r.szRule == "stayfocused") { PWINDOW->m_bStayFocused = true; - } else if (r.szRule.find("group") == 0) { + } else if (r.szRule.starts_with("group")) { if (PWINDOW->m_eGroupRules & GROUP_OVERRIDE) continue; @@ -246,7 +246,7 @@ void Events::listener_mapWindow(void* owner, void* data) { } vPrev = v; } - } else if (r.szRule.find("idleinhibit") == 0) { + } else if (r.szRule.starts_with("idleinhibit")) { auto IDLERULE = r.szRule.substr(r.szRule.find_first_of(' ') + 1); if (IDLERULE == "none") { @@ -273,7 +273,7 @@ void Events::listener_mapWindow(void* owner, void* data) { const CVarList WORKSPACEARGS = CVarList(requestedWorkspace, 0, ' '); if (!WORKSPACEARGS[0].empty()) { - if (WORKSPACEARGS[WORKSPACEARGS.size() - 1].find("silent") == 0) + if (WORKSPACEARGS[WORKSPACEARGS.size() - 1].starts_with("silent")) workspaceSilent = true; std::string requestedWorkspaceName; @@ -309,7 +309,7 @@ void Events::listener_mapWindow(void* owner, void* data) { // size and move rules for (auto& r : WINDOWRULES) { - if (r.szRule.find("size") == 0) { + if (r.szRule.starts_with("size")) { try { const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); @@ -331,7 +331,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->setHidden(false); } catch (...) { Debug::log(LOG, "Rule size failed, rule: {} -> {}", r.szRule, r.szValue); } - } else if (r.szRule.find("minsize") == 0) { + } else if (r.szRule.starts_with("minsize")) { try { const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); @@ -345,7 +345,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->setHidden(false); } catch (...) { Debug::log(LOG, "Rule minsize failed, rule: {} -> {}", r.szRule, r.szValue); } - } else if (r.szRule.find("maxsize") == 0) { + } else if (r.szRule.starts_with("maxsize")) { try { const auto VALUE = r.szRule.substr(r.szRule.find(' ') + 1); const auto SIZEXSTR = VALUE.substr(0, VALUE.find(' ')); @@ -359,16 +359,16 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->setHidden(false); } catch (...) { Debug::log(LOG, "Rule maxsize failed, rule: {} -> {}", r.szRule, r.szValue); } - } else if (r.szRule.find("move") == 0) { + } else if (r.szRule.starts_with("move")) { try { auto value = r.szRule.substr(r.szRule.find(' ') + 1); - const bool ONSCREEN = value.find("onscreen") == 0; + const bool ONSCREEN = value.starts_with("onscreen"); if (ONSCREEN) value = value.substr(value.find_first_of(' ') + 1); - const bool CURSOR = value.find("cursor") == 0; + const bool CURSOR = value.starts_with("cursor"); if (CURSOR) value = value.substr(value.find_first_of(' ') + 1); @@ -379,7 +379,7 @@ void Events::listener_mapWindow(void* owner, void* data) { int posX = 0; int posY = 0; - if (POSXSTR.find("100%-") == 0) { + if (POSXSTR.starts_with("100%-")) { const auto POSXRAW = POSXSTR.substr(5); posX = PMONITOR->vecSize.x - (!POSXRAW.contains('%') ? std::stoi(POSXRAW) : std::stof(POSXRAW.substr(0, POSXRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.x); @@ -398,7 +398,7 @@ void Events::listener_mapWindow(void* owner, void* data) { } } - if (POSYSTR.find("100%-") == 0) { + if (POSYSTR.starts_with("100%-")) { const auto POSYRAW = POSYSTR.substr(5); posY = PMONITOR->vecSize.y - (!POSYRAW.contains('%') ? std::stoi(POSYRAW) : std::stof(POSYRAW.substr(0, POSYRAW.length() - 1)) * 0.01 * PMONITOR->vecSize.y); @@ -433,7 +433,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->setHidden(false); } catch (...) { Debug::log(LOG, "Rule move failed, rule: {} -> {}", r.szRule, r.szValue); } - } else if (r.szRule.find("center") == 0) { + } else if (r.szRule.starts_with("center")) { auto RESERVEDOFFSET = Vector2D(); const auto ARGS = CVarList(r.szRule, 2, ' '); if (ARGS[1] == "1") diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 47c1180a..b3236725 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -250,7 +250,7 @@ bool isDirection(const std::string& arg) { int getWorkspaceIDFromString(const std::string& in, std::string& outName) { int result = INT_MAX; - if (in.find("special") == 0) { + if (in.starts_with("special")) { outName = "special"; if (in.length() > 8) { @@ -264,7 +264,7 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { } return SPECIAL_WORKSPACE_START; - } else if (in.find("name:") == 0) { + } else if (in.starts_with("name:")) { const auto WORKSPACENAME = in.substr(in.find_first_of(':') + 1); const auto WORKSPACE = g_pCompositor->getWorkspaceByName(WORKSPACENAME); if (!WORKSPACE) { @@ -273,14 +273,14 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { result = WORKSPACE->m_iID; } outName = WORKSPACENAME; - } else if (in.find("empty") == 0) { + } else if (in.starts_with("empty")) { int id = 0; while (++id < INT_MAX) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(id); if (!PWORKSPACE || (g_pCompositor->getWindowsOnWorkspace(id) == 0)) return id; } - } else if (in.find("prev") == 0) { + } else if (in.starts_with("prev")) { if (!g_pCompositor->m_pLastMonitor) return INT_MAX; @@ -391,12 +391,12 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { int beginID = finalWSID; int curID = finalWSID; while (--curID > 0 && remainingWSes > 0) { - if (invalidWSes.find(curID) == invalidWSes.end()) { + if (!invalidWSes.contains(curID)) { remainingWSes--; } finalWSID = curID; } - if (finalWSID <= 0 || invalidWSes.find(finalWSID) != invalidWSes.end()) { + if (finalWSID <= 0 || invalidWSes.contains(finalWSID)) { if (namedWSes.size()) { // Go to the named workspaces // Need remainingWSes more @@ -416,7 +416,7 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { if (walkDir == '+') { int curID = finalWSID; while (++curID < INT32_MAX && remainingWSes > 0) { - if (invalidWSes.find(curID) == invalidWSes.end()) { + if (!invalidWSes.contains(curID)) { remainingWSes--; } finalWSID = curID; @@ -594,8 +594,8 @@ int64_t getPPIDof(int64_t pid) { return 0; #else - std::string dir = "/proc/" + std::to_string(pid) + "/status"; - FILE* infile; + std::string dir = "/proc/" + std::to_string(pid) + "/status"; + FILE* infile; infile = fopen(dir.c_str(), "r"); if (!infile) @@ -628,11 +628,11 @@ int64_t getPPIDof(int64_t pid) { } int64_t configStringToInt(const std::string& VALUE) { - if (VALUE.find("0x") == 0) { + if (VALUE.starts_with("0x")) { // Values with 0x are hex const auto VALUEWITHOUTHEX = VALUE.substr(2); return stol(VALUEWITHOUTHEX, nullptr, 16); - } else if (VALUE.find("rgba(") == 0 && VALUE.find(')') == VALUE.length() - 1) { + } else if (VALUE.starts_with("rgba(") && VALUE.ends_with(')')) { const auto VALUEWITHOUTFUNC = VALUE.substr(5, VALUE.length() - 6); if (removeBeginEndSpacesTabs(VALUEWITHOUTFUNC).length() != 8) { @@ -644,7 +644,7 @@ int64_t configStringToInt(const std::string& VALUE) { // now we need to RGBA -> ARGB. The config holds ARGB only. return (RGBA >> 8) + 0x1000000 * (RGBA & 0xFF); - } else if (VALUE.find("rgb(") == 0 && VALUE.find(')') == VALUE.length() - 1) { + } else if (VALUE.starts_with("rgb(") && VALUE.ends_with(')')) { const auto VALUEWITHOUTFUNC = VALUE.substr(4, VALUE.length() - 5); if (removeBeginEndSpacesTabs(VALUEWITHOUTFUNC).length() != 6) { @@ -655,9 +655,9 @@ int64_t configStringToInt(const std::string& VALUE) { const auto RGB = std::stol(VALUEWITHOUTFUNC, nullptr, 16); return RGB + 0xFF000000; // 0xFF for opaque - } else if (VALUE.find("true") == 0 || VALUE.find("on") == 0 || VALUE.find("yes") == 0) { + } else if (VALUE.starts_with("true") || VALUE.starts_with("on") || VALUE.starts_with("yes")) { return 1; - } else if (VALUE.find("false") == 0 || VALUE.find("off") == 0 || VALUE.find("no") == 0) { + } else if (VALUE.starts_with("false") || VALUE.starts_with("off") || VALUE.starts_with("no")) { return 0; } return std::stoll(VALUE); diff --git a/src/helpers/WLClasses.cpp b/src/helpers/WLClasses.cpp index 1fa807fa..6923d6a5 100644 --- a/src/helpers/WLClasses.cpp +++ b/src/helpers/WLClasses.cpp @@ -20,7 +20,7 @@ void SLayerSurface::applyRules() { noAnimations = true; else if (rule.rule == "blur") forceBlur = true; - else if (rule.rule.find("ignorealpha") == 0 || rule.rule.find("ignorezero") == 0) { + else if (rule.rule.starts_with("ignorealpha") || rule.rule.starts_with("ignorezero")) { const auto FIRST_SPACE_POS = rule.rule.find_first_of(' '); std::string alphaValue = ""; if (FIRST_SPACE_POS != std::string::npos) @@ -31,7 +31,7 @@ void SLayerSurface::applyRules() { if (!alphaValue.empty()) ignoreAlphaValue = std::stof(alphaValue); } catch (...) { Debug::log(ERR, "Invalid value passed to ignoreAlpha"); } - } else if (rule.rule.find("xray") == 0) { + } else if (rule.rule.starts_with("xray")) { CVarList vars{rule.rule, 0, ' '}; try { xray = configStringToInt(vars[1]); diff --git a/src/helpers/Workspace.cpp b/src/helpers/Workspace.cpp index 51d29e5e..3264b27f 100644 --- a/src/helpers/Workspace.cpp +++ b/src/helpers/Workspace.cpp @@ -40,7 +40,7 @@ CWorkspace::~CWorkspace() { void CWorkspace::startAnim(bool in, bool left, bool instant) { const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle; - if (ANIMSTYLE.find("slidefade") == 0) { + if (ANIMSTYLE.starts_with("slidefade")) { const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); float movePerc = 100.f; @@ -54,7 +54,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { m_fAlpha.setValueAndWarp(1.f); m_vRenderOffset.setValueAndWarp(Vector2D(0, 0)); - if (ANIMSTYLE.find("slidefadevert") == 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))); diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index db3ebe52..a7d05030 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -256,8 +256,8 @@ void CAnimationManager::tick() { const auto EXTENTS = PDECO->getWindowDecorationExtents(); wlr_box dmg = {PWINDOW->m_vRealPosition.vec().x - EXTENTS.topLeft.x, PWINDOW->m_vRealPosition.vec().y - EXTENTS.topLeft.y, - PWINDOW->m_vRealSize.vec().x + EXTENTS.topLeft.x + EXTENTS.bottomRight.x, - PWINDOW->m_vRealSize.vec().y + EXTENTS.topLeft.y + EXTENTS.bottomRight.y}; + PWINDOW->m_vRealSize.vec().x + EXTENTS.topLeft.x + EXTENTS.bottomRight.x, + PWINDOW->m_vRealSize.vec().y + EXTENTS.topLeft.y + EXTENTS.bottomRight.y}; if (!*PSHADOWIGNOREWINDOW) { // easy, damage the entire box @@ -429,7 +429,7 @@ void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) { if (pWindow->m_sAdditionalConfigData.animationStyle != "") { // the window has config'd special anim - if (pWindow->m_sAdditionalConfigData.animationStyle.find("slide") == 0) { + if (pWindow->m_sAdditionalConfigData.animationStyle.starts_with("slide")) { if (pWindow->m_sAdditionalConfigData.animationStyle.contains(' ')) { // has a direction animationSlide(pWindow, pWindow->m_sAdditionalConfigData.animationStyle.substr(pWindow->m_sAdditionalConfigData.animationStyle.find(' ') + 1), close); @@ -458,7 +458,7 @@ void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) { // anim popin, fallback float minPerc = 0.f; - if (ANIMSTYLE.find("%") != 0) { + if (!ANIMSTYLE.starts_with("%")) { try { auto percstr = ANIMSTYLE.substr(ANIMSTYLE.find_last_of(' ')); minPerc = std::stoi(percstr.substr(0, percstr.length() - 1)); @@ -473,10 +473,10 @@ void CAnimationManager::onWindowPostCreateClose(CWindow* pWindow, bool close) { } std::string CAnimationManager::styleValidInConfigVar(const std::string& config, const std::string& style) { - if (config.find("window") == 0) { + if (config.starts_with("window")) { if (style == "slide") { return ""; - } else if (style.find("popin") == 0) { + } else if (style.starts_with("popin")) { // try parsing float minPerc = 0.f; if (style.find("%") != std::string::npos) { @@ -497,7 +497,7 @@ std::string CAnimationManager::styleValidInConfigVar(const std::string& config, } else if (config == "workspaces" || config == "specialWorkspace") { if (style == "slide" || style == "slidevert" || style == "fade") return ""; - else if (style.find("slidefade") == 0) { + else if (style.starts_with("slidefade")) { // try parsing float movePerc = 0.f; if (style.find("%") != std::string::npos) { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index fd298d34..cd99c61f 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -808,9 +808,9 @@ void CKeybindManager::changeworkspace(std::string args) { const auto PMONITOR = g_pCompositor->m_pLastMonitor; const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); - const bool EXPLICITPREVIOUS = args.find("previous") == 0; + const bool EXPLICITPREVIOUS = args.starts_with("previous"); - if (args.find("previous") == 0) { + if (args.starts_with("previous")) { // Do nothing if there's no previous workspace, otherwise switch to it. if (PCURRENTWORKSPACE->m_sPrevWorkspace.iID == -1) { Debug::log(LOG, "No previous workspace to change to"); @@ -1094,7 +1094,7 @@ void CKeybindManager::swapActive(std::string args) { void CKeybindManager::moveActiveTo(std::string args) { char arg = args[0]; - if (args.find("mon:") == 0) { + if (args.starts_with("mon:")) { const auto PNEWMONITOR = g_pCompositor->getMonitorFromString(args.substr(4)); if (!PNEWMONITOR) return; @@ -1221,7 +1221,7 @@ void CKeybindManager::alterSplitRatio(std::string args) { } if (splitratio == 0) { - if (args.find("exact") == 0) { + if (args.starts_with("exact")) { exact = true; splitratio = getPlusMinusKeywordResult(args.substr(5), 0); } else { @@ -1721,10 +1721,10 @@ void CKeybindManager::toggleOpaque(std::string unused) { } void CKeybindManager::dpms(std::string arg) { - bool enable = arg.find("on") == 0; + bool enable = arg.starts_with("on"); std::string port = ""; - if (arg.find("toggle") == 0) + if (arg.starts_with("toggle")) enable = !std::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](const auto& other) { return !other->dpmsStatus; }); // enable if any is off if (arg.find_first_of(' ') != std::string::npos) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index f79278e3..fb93b7bc 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1001,7 +1001,7 @@ void CInputManager::setPointerConfigs() { libinput_device_config_accel_set_profile(LIBINPUTDEV, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE); } else if (ACCELPROFILE == "flat") { libinput_device_config_accel_set_profile(LIBINPUTDEV, LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT); - } else if (ACCELPROFILE.find("custom") == 0) { + } else if (ACCELPROFILE.starts_with("custom")) { CVarList args = {ACCELPROFILE, 0, ' '}; try { double step = std::stod(args[1]); @@ -1582,7 +1582,7 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) { wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; eBorderIconDirection direction = BORDERICON_NONE; wlr_box boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE), - box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; + box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; if (!wlr_box_contains_point(&boxFullGrabInput, mouseCoords.x, mouseCoords.y) || (!m_lCurrentlyHeldButtons.empty() && !currentlyDraggedWindow)) { direction = BORDERICON_NONE; diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index ebed67cd..360397eb 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -51,7 +51,7 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) { static auto* const PSWIPENUMBER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_numbered")->intValue; static auto* const PSWIPEUSER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_use_r")->intValue; const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.find("slidefadevert") == 0; + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); // commit std::string wsname = ""; @@ -200,7 +200,7 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { static auto* const PSWIPEUSER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_use_r")->intValue; const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.find("slidefadevert") == 0; + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); m_sActiveSwipe.delta += VERTANIMS ? (*PSWIPEINVR ? -e->dy : e->dy) : (*PSWIPEINVR ? -e->dx : e->dx); diff --git a/src/plugins/PluginAPI.cpp b/src/plugins/PluginAPI.cpp index ae289396..8d2f6627 100644 --- a/src/plugins/PluginAPI.cpp +++ b/src/plugins/PluginAPI.cpp @@ -153,7 +153,7 @@ APICALL bool HyprlandAPI::addConfigValue(HANDLE handle, const std::string& name, if (!PLUGIN) return false; - if (name.find("plugin:") != 0) + if (!name.starts_with("plugin:")) return false; g_pConfigManager->addPluginConfigVar(handle, name, value); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 64703205..8ad8e0c1 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -122,7 +122,7 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { m_iWLROutputFb = m_iCurrentOutputFb; // ensure a framebuffer for the monitor exists - if (m_mMonitorRenderResources.find(pMonitor) == m_mMonitorRenderResources.end() || m_RenderData.pCurrentMonData->primaryFB.m_vSize != pMonitor->vecPixelSize) { + if (!m_mMonitorRenderResources.contains(pMonitor) || m_RenderData.pCurrentMonData->primaryFB.m_vSize != pMonitor->vecPixelSize) { m_RenderData.pCurrentMonData->stencilTex.allocate(); m_RenderData.pCurrentMonData->primaryFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; From 1f582457cfdea7f2d0d2028f7b3dbabbebd0e164 Mon Sep 17 00:00:00 2001 From: Alexander Seleznev Date: Sun, 15 Oct 2023 21:19:07 +0300 Subject: [PATCH 083/513] Debug: respect logging settings for wlr (#3584) --- src/debug/Log.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/debug/Log.cpp b/src/debug/Log.cpp index 8850a0af..98eeebc9 100644 --- a/src/debug/Log.cpp +++ b/src/debug/Log.cpp @@ -10,6 +10,12 @@ void Debug::init(const std::string& IS) { } void Debug::wlrLog(wlr_log_importance level, const char* fmt, va_list args) { + if (disableLogs && *disableLogs) + return; + + if (level > wlr_log_get_verbosity()) + return; + char* outputStr = nullptr; std::ofstream ofs; From 8af3e7beebb96eceb8a094a20286d57e3b135938 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 15 Oct 2023 22:35:45 +0100 Subject: [PATCH 084/513] cmake: search for systemd headers first --- CMakeLists.txt | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 04008a8b..d9698d45 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -149,13 +149,18 @@ if(NO_SYSTEMD) message(STATUS "SYSTEMD support is disabled...") else() message(STATUS "SYSTEMD support is requested (NO_SYSTEMD not defined) checking deps...") - pkg_check_modules(LIBSYSTEMD libsystemd) check_include_file("systemd/sd-daemon.h" SYSTEMDH) - if(LIBSYSTEMD_FOUND AND SYSTEMDH) - add_compile_definitions(USES_SYSTEMD) - target_link_libraries(Hyprland "${LIBSYSTEMD_LIBRARIES}") + if(SYSTEMDH) + pkg_check_modules(LIBSYSTEMD libsystemd) + if (LIBSYSTEMD_FOUND) + add_compile_definitions(USES_SYSTEMD) + target_link_libraries(Hyprland "${LIBSYSTEMD_LIBRARIES}") + message(STATUS "Systemd found") + else() + message(WARNING "Systemd support requested but systemd libraries were not found") + endif() else() - message(WARNING "Systemd support requested but libsystemd or systemd headers were not found") + message(WARNING "Systemd support requested but systemd headers were not found") endif() endif() From 5b8cfdf2efc44106b61e60c642fd964823fd89f3 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 16 Oct 2023 17:17:00 +0100 Subject: [PATCH 085/513] props: bump ver to v0.31.0 --- props.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/props.json b/props.json index 2c6747a2..d813a0c2 100644 --- a/props.json +++ b/props.json @@ -1,3 +1,3 @@ { - "version": "0.30.0" + "version": "0.31.0" } \ No newline at end of file From 54e1c2ccbdfa6dfade63221b5df02bf8578d96a6 Mon Sep 17 00:00:00 2001 From: memchr <118117622+memchr@users.noreply.github.com> Date: Mon, 16 Oct 2023 16:39:12 +0000 Subject: [PATCH 086/513] fix(build): do not include wlr headers directly, use includes.hpp instead. (#3587) --- src/debug/Log.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/debug/Log.hpp b/src/debug/Log.hpp index 125ed7f4..085465c9 100644 --- a/src/debug/Log.hpp +++ b/src/debug/Log.hpp @@ -1,10 +1,10 @@ #pragma once #include -#include #include #include #include #include +#include "../includes.hpp" #include "../helpers/MiscFunctions.hpp" #define LOGMESSAGESIZE 1024 @@ -79,4 +79,4 @@ namespace Debug { } void wlrLog(wlr_log_importance level, const char* fmt, va_list args); -}; \ No newline at end of file +}; From 93676f91a059d85f9d29a99684fb19b40af5abda Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Tue, 17 Oct 2023 00:29:06 +0000 Subject: [PATCH 087/513] renderer: cast std::clamp args to be of the same type (#3589) src/render/OpenGL.cpp:1769:41: error: no matching function for call to 'clamp' const auto FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, -1L, 2L); ^~~~~~~~~~ /usr/include/c++/v1/__algorithm/clamp.h:38:1: note: candidate template ignored: deduced conflicting types for parameter '_Tp' ('int64_t' (aka 'long long') vs. 'long') clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi) ^ /usr/include/c++/v1/__algorithm/clamp.h:27:1: note: candidate function template not viable: requires 4 arguments, but 3 were provided clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi, _Compare __comp) ^ --- src/render/OpenGL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 8ad8e0c1..2d8ee92b 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1766,7 +1766,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { static auto* const PFORCEHYPRCHAN = &g_pConfigManager->getConfigValuePtr("misc:force_hypr_chan")->intValue; static auto* const PFORCEWALLPAPER = &g_pConfigManager->getConfigValuePtr("misc:force_default_wallpaper")->intValue; - const auto FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, -1L, 2L); + const auto FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, static_cast(-1L), static_cast(2L)); // release the last tex if exists const auto PTEX = &m_mMonitorBGTextures[pMonitor]; From 421f5fb221322c028092dcf3a943f26a30d45b9f Mon Sep 17 00:00:00 2001 From: eriedaberrie <64395218+eriedaberrie@users.noreply.github.com> Date: Tue, 17 Oct 2023 03:41:27 -0700 Subject: [PATCH 088/513] events: make new windows taking over fullscreen keep the existing mode (#3588) --- src/events/Windows.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 84582537..a77c298f 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -473,6 +473,8 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->m_bNoInitialFocus = true; else if (*PNEWTAKESOVERFS == 2) g_pCompositor->setWindowFullscreen(g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID), false, FULLSCREEN_INVALID); + else if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) + requestsMaximize = true; else requestsFullscreen = true; } From 210be10c92275c73fb37512f7abfde1eece9026b Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Tue, 17 Oct 2023 04:05:38 -0700 Subject: [PATCH 089/513] meson/nix: Fix meson.build nix patch (#3594) `meson.build` was modified in #3547 but `nix/patches/meson-build.patch` was not updated to reflect the changes. --- nix/patches/meson-build.patch | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/nix/patches/meson-build.patch b/nix/patches/meson-build.patch index 23442172..b8f784e9 100644 --- a/nix/patches/meson-build.patch +++ b/nix/patches/meson-build.patch @@ -1,10 +1,10 @@ diff --git a/meson.build b/meson.build -index 726933bc..28b4d9ac 100644 +index 1d2c7f9f..c5ef4e67 100644 --- a/meson.build +++ b/meson.build -@@ -29,20 +29,7 @@ add_project_arguments( - ], - language: 'cpp') +@@ -33,20 +33,7 @@ if cpp_compiler.check_header('execinfo.h') + add_project_arguments('-DHAS_EXECINFO', language: 'cpp') + endif -wlroots = subproject('wlroots', default_options: ['examples=false', 'renderers=gles2']) -have_xwlr = wlroots.get_variable('features').get('xwayland') @@ -24,7 +24,7 @@ index 726933bc..28b4d9ac 100644 add_project_arguments('-DNO_XWAYLAND', language: 'cpp') endif -@@ -71,8 +58,6 @@ foreach file : headers +@@ -75,8 +62,6 @@ foreach file : headers install_headers(file, subdir: 'hyprland', preserve_path: true) endforeach @@ -34,7 +34,7 @@ index 726933bc..28b4d9ac 100644 subdir('src') subdir('hyprctl') diff --git a/src/meson.build b/src/meson.build -index 2065c6f5..55530605 100644 +index 0af864b9..38723b8c 100644 --- a/src/meson.build +++ b/src/meson.build @@ -9,16 +9,16 @@ executable('Hyprland', src, From 20e7ccd48033dcacc233b2a2f46d385049bf299b Mon Sep 17 00:00:00 2001 From: thejch <66577496+thejch@users.noreply.github.com> Date: Tue, 17 Oct 2023 04:06:16 -0700 Subject: [PATCH 090/513] master: fix resizing wrong window behind in special workspace (#3591) --- src/layout/MasterLayout.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 2de43d04..f44e04e3 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -742,8 +742,9 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne default: UNREACHABLE(); } + const auto workspaceIdForResizing = PMONITOR->specialWorkspaceID == 0 ? PMONITOR->activeWorkspace : PMONITOR->specialWorkspaceID; for (auto& n : m_lMasterNodesData) { - if (n.isMaster && n.workspaceID == PMONITOR->activeWorkspace) + if (n.isMaster && n.workspaceID == workspaceIdForResizing) n.percMaster = std::clamp(n.percMaster + delta, 0.05, 0.95); } From 784f8a88fb59c9674648e275e78903ac15bbbf9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= <123550+andresilva@users.noreply.github.com> Date: Tue, 17 Oct 2023 17:00:39 +0100 Subject: [PATCH 091/513] input: don't reset cursor movement timer on simulateMouseMovement (#3595) Fixes #2570 --- src/managers/input/InputManager.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index fb93b7bc..ab5be4bc 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -41,8 +41,6 @@ void CInputManager::simulateMouseMovement() { clock_gettime(CLOCK_MONOTONIC, &now); m_vLastCursorPosFloored = m_vLastCursorPosFloored - Vector2D(1, 1); // hack: force the mouseMoveUnified to report without making this a refocus. mouseMoveUnified(now.tv_sec * 1000 + now.tv_nsec / 10000000); - - m_tmrLastCursorMovement.reset(); } void CInputManager::sendMotionEventsToFocused() { From a0b675ec9e57af8bc631fc8cc54d062b58669a9f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 17 Oct 2023 20:09:54 +0100 Subject: [PATCH 092/513] binds: add ignoreMods flag --- src/config/ConfigManager.cpp | 10 +++++++--- src/managers/KeybindManager.cpp | 3 ++- src/managers/KeybindManager.hpp | 4 +++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 5ae341f8..2c3f6474 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -832,6 +832,7 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v bool mouse = false; bool nonConsuming = false; bool transparent = false; + bool ignoreMods = false; const auto BINDARGS = command.substr(4); for (auto& arg : BINDARGS) { @@ -847,6 +848,8 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v nonConsuming = true; } else if (arg == 't') { transparent = true; + } else if (arg == 'i') { + ignoreMods = true; } else { parseError = "bind: invalid flag"; return; @@ -904,12 +907,13 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v if (KEY != "") { if (isNumber(KEY) && std::stoi(KEY) > 9) - g_pKeybindManager->addKeybind(SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent}); + g_pKeybindManager->addKeybind( + SKeybind{"", std::stoi(KEY), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent, ignoreMods}); else if (KEY.starts_with("code:") && isNumber(KEY.substr(5))) g_pKeybindManager->addKeybind( - SKeybind{"", std::stoi(KEY.substr(5)), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent}); + SKeybind{"", std::stoi(KEY.substr(5)), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent, ignoreMods}); else - g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent}); + g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent, ignoreMods}); } } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index cd99c61f..7e0b7620 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -435,7 +435,8 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string& const bool IGNORECONDITIONS = SPECIALDISPATCHER && !pressed && SPECIALTRIGGERED; // ignore mods. Pass, global dispatchers should be released immediately once the key is released. - if (!IGNORECONDITIONS && (modmask != k.modmask || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || k.shadowed)) + if (!IGNORECONDITIONS && + ((modmask != k.modmask && !k.ignoreMods) || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || k.shadowed)) continue; if (!key.empty()) { diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 9c63249e..8a0b3b89 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -23,12 +23,14 @@ struct SKeybind { bool mouse = false; bool nonConsuming = false; bool transparent = false; + bool ignoreMods = false; // DO NOT INITIALIZE bool shadowed = false; }; -enum eFocusWindowMode { +enum eFocusWindowMode +{ MODE_CLASS_REGEX = 0, MODE_TITLE_REGEX, MODE_ADDRESS, From d70cc88dab11bc6d1095523a0ce655dff40b27a2 Mon Sep 17 00:00:00 2001 From: memchr <118117622+memchr@users.noreply.github.com> Date: Wed, 18 Oct 2023 23:09:06 +0000 Subject: [PATCH 093/513] meson: generate version.h before install_headers (#3612) Otherwise, meson install would not install version.h as a header in a clean build. --- meson.build | 4 ++-- nix/patches/meson-build.patch | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/meson.build b/meson.build index 1d2c7f9f..de29528e 100644 --- a/meson.build +++ b/meson.build @@ -69,14 +69,14 @@ if get_option('buildtype') == 'debug' add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp') endif +version_h = run_command('sh', '-c', 'scripts/generateVersion.sh') + globber = run_command('find', 'src', '-name', '*.h*', check: true) headers = globber.stdout().strip().split('\n') foreach file : headers install_headers(file, subdir: 'hyprland', preserve_path: true) endforeach -version_h = run_command('sh', '-c', 'scripts/generateVersion.sh') - subdir('protocols') subdir('src') subdir('hyprctl') diff --git a/nix/patches/meson-build.patch b/nix/patches/meson-build.patch index b8f784e9..844eacae 100644 --- a/nix/patches/meson-build.patch +++ b/nix/patches/meson-build.patch @@ -24,15 +24,15 @@ index 1d2c7f9f..c5ef4e67 100644 add_project_arguments('-DNO_XWAYLAND', language: 'cpp') endif -@@ -75,8 +62,6 @@ foreach file : headers - install_headers(file, subdir: 'hyprland', preserve_path: true) - endforeach +@@ -69,8 +56,6 @@ if get_option('buildtype') == 'debug' + add_project_arguments('-DHYPRLAND_DEBUG', language: 'cpp') + endif -version_h = run_command('sh', '-c', 'scripts/generateVersion.sh') - - subdir('protocols') - subdir('src') - subdir('hyprctl') + globber = run_command('find', 'src', '-name', '*.h*', check: true) + headers = globber.stdout().strip().split('\n') + foreach file : headers diff --git a/src/meson.build b/src/meson.build index 0af864b9..38723b8c 100644 --- a/src/meson.build From 6e15590e98ca643d06eacc84adf161bcef705c0b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 19 Oct 2023 14:04:50 +0100 Subject: [PATCH 094/513] shaders: support changing the outer radius of borders independently --- src/render/OpenGL.cpp | 4 +++- src/render/OpenGL.hpp | 2 +- src/render/Shader.hpp | 1 + src/render/shaders/Border.hpp | 22 ++++++++++++++++------ 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 2d8ee92b..29574887 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -349,6 +349,7 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shBORDER1.fullSize = glGetUniformLocation(prog, "fullSize"); m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed = glGetUniformLocation(prog, "fullSizeUntransformed"); m_RenderData.pCurrentMonData->m_shBORDER1.radius = glGetUniformLocation(prog, "radius"); + m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter = glGetUniformLocation(prog, "radiusOuter"); m_RenderData.pCurrentMonData->m_shBORDER1.gradient = glGetUniformLocation(prog, "gradient"); m_RenderData.pCurrentMonData->m_shBORDER1.gradientLength = glGetUniformLocation(prog, "gradientLength"); m_RenderData.pCurrentMonData->m_shBORDER1.angle = glGetUniformLocation(prog, "angle"); @@ -1293,7 +1294,7 @@ void pushVert2D(float x, float y, float* arr, int& counter, wlr_box* box) { counter++; } -void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad, int round, int borderSize, float a) { +void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad, int round, int borderSize, float a, int outerRound) { RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); @@ -1359,6 +1360,7 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad, glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSize, (float)FULLSIZE.x, (float)FULLSIZE.y); glUniform2f(m_RenderData.pCurrentMonData->m_shBORDER1.fullSizeUntransformed, (float)box->width, (float)box->height); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radius, round); + glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.radiusOuter, outerRound == -1 ? round : outerRound); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.thick, scaledBorderSize); glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBORDER1.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index c04e8c65..61e8ffdb 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -109,7 +109,7 @@ class CHyprOpenGLImpl { void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); void renderRoundedShadow(wlr_box*, int round, int range, float a = 1.0); - void renderBorder(wlr_box*, const CGradientValueData&, int round, int borderSize, float a = 1.0); + void renderBorder(wlr_box*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); void saveMatrix(); void setMatrixScaleTranslate(const Vector2D& translate, const float& scale); diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp index 5945c157..e972eeb9 100644 --- a/src/render/Shader.hpp +++ b/src/render/Shader.hpp @@ -23,6 +23,7 @@ class CShader { GLint fullSize = -1; GLint fullSizeUntransformed = -1; GLint radius = -1; + GLint radiusOuter = -1; GLint thick = -1; diff --git a/src/render/shaders/Border.hpp b/src/render/shaders/Border.hpp index f7b9d94d..79493da9 100644 --- a/src/render/shaders/Border.hpp +++ b/src/render/shaders/Border.hpp @@ -12,6 +12,7 @@ uniform vec2 topLeft; uniform vec2 fullSize; uniform vec2 fullSizeUntransformed; uniform float radius; +uniform float radiusOuter; uniform float thick; uniform vec4 gradient[10]; @@ -51,6 +52,7 @@ vec4 getColorForCoord(vec2 normalizedCoord) { void main() { highp vec2 pixCoord = vec2(gl_FragCoord); + highp vec2 pixCoordOuter = pixCoord; highp vec2 originalPixCoord = v_texcoord; originalPixCoord *= fullSizeUntransformed; float additionalAlpha = 1.0; @@ -61,25 +63,33 @@ void main() { pixCoord -= topLeft + fullSize * 0.5; pixCoord *= vec2(lessThan(pixCoord, vec2(0.0))) * -2.0 + 1.0; + pixCoordOuter = pixCoord; pixCoord -= fullSize * 0.5 - radius; - pixCoord += vec2(1.0, 1.0) / fullSize; // center the pix dont make it top-left + pixCoordOuter -= fullSize * 0.5 - radiusOuter; + + // center the pixes dont make it top-left + pixCoord += vec2(1.0, 1.0) / fullSize; + pixCoordOuter += vec2(1.0, 1.0) / fullSize; if (min(pixCoord.x, pixCoord.y) > 0.0 && radius > 0.0) { - float dist = length(pixCoord); + float distOuter = length(pixCoordOuter); float h = (thick / 2.0); if (dist < radius - h) { // lower float normalized = smoothstep(0.0, 1.0, dist - radius + thick + 0.5); additionalAlpha *= normalized; - } else { + done = true; + } else if (min(pixCoordOuter.x, pixCoordOuter.y) > 0.0) { // higher - float normalized = 1.0 - smoothstep(0.0, 1.0, dist - radius + 0.5); + float normalized = 1.0 - smoothstep(0.0, 1.0, distOuter - radiusOuter + 0.5); additionalAlpha *= normalized; + done = true; + } else if (distOuter < radiusOuter - h) { + additionalAlpha = 1.0; + done = true; } - - done = true; } // now check for other shit From d994e6aea6d96e423004952a2fa8b02acf9d004d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 20 Oct 2023 01:00:58 +1100 Subject: [PATCH 095/513] cmake: Fix error building without CMAKE_BUILD_TYPE being set (#3590) * Fix error building without CMAKE_BUILD_TYPE being set This resolves the error building without a CMAKE_BUILD_TYPE. CMake Error at CMakeLists.txt:36 (string): string no output variable specified * CMake: convert CMake's build type to meson build type Fix error when the CMAKE_BUILD_TYPE variable isn't set & properly convert the build type to mesons build type. --- CMakeLists.txt | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d9698d45..5429050b 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,7 +33,24 @@ add_subdirectory("subprojects/udis86") message(STATUS "Setting up wlroots") include(ExternalProject) -string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER) + +if(CMAKE_BUILD_TYPE) + string(TOLOWER ${CMAKE_BUILD_TYPE} BUILDTYPE_LOWER) + if(BUILDTYPE_LOWER STREQUAL "release") + # Pass. + elseif(BUILDTYPE_LOWER STREQUAL "debug") + # Pass. + elseif(BUILDTYPE_LOWER STREQUAL "relwithdebinfo") + set(BUILDTYPE_LOWER "debugoptimized") + elseif(BUILDTYPE_LOWER STREQUAL "minsizerel") + set(BUILDTYPE_LOWER "minsize") + else() + set(BUILDTYPE_LOWER "release") + endif() +else() + set(BUILDTYPE_LOWER "release") +endif() + ExternalProject_Add( wlroots PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots @@ -230,4 +247,4 @@ protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v protocol("staging/cursor-shape/cursor-shape-v1.xml" "cursor-shape-v1" false) # hyprctl -add_subdirectory(hyprctl) \ No newline at end of file +add_subdirectory(hyprctl) From ba5f1d87838978ae92d4989545a083e28ef58d6f Mon Sep 17 00:00:00 2001 From: q234rty Date: Thu, 19 Oct 2023 22:59:24 +0800 Subject: [PATCH 096/513] cmake: Map cmake None to meson empty (#3614) While not explicitly mentioned by the cmake documentation, cmake upstream seems to think of None as a vaild CMAKE_BUILD_TYPE. [1] Handle it properly by mapping it to meson's empty. [1]: https://github.com/Kitware/CMake/commit/ce1cadd35a26bd44879675581d8e70b00ff8e0fc --- CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5429050b..709a8eaf 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,8 @@ if(CMAKE_BUILD_TYPE) set(BUILDTYPE_LOWER "debugoptimized") elseif(BUILDTYPE_LOWER STREQUAL "minsizerel") set(BUILDTYPE_LOWER "minsize") + elseif(BUILDTYPE_LOWER STREQUAL "none") + set(BUILDTYPE_LOWER "empty") else() set(BUILDTYPE_LOWER "release") endif() From 386708563c3d9d85ffd60b4eeb6c767d29f948db Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 19 Oct 2023 16:04:48 +0100 Subject: [PATCH 097/513] workspacerules: search for special properly fixes #3537 --- src/config/ConfigManager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 2c3f6474..f0961aa0 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1850,7 +1850,10 @@ SMonitorRule CConfigManager::getMonitorRuleFor(const std::string& name, const st SWorkspaceRule CConfigManager::getWorkspaceRuleFor(CWorkspace* pWorkspace) { const auto WORKSPACEIDSTR = std::to_string(pWorkspace->m_iID); const auto IT = std::find_if(m_dWorkspaceRules.begin(), m_dWorkspaceRules.end(), [&](const auto& other) { - return other.workspaceName == pWorkspace->m_szName || (pWorkspace->m_iID > 0 && WORKSPACEIDSTR == other.workspaceName); + return other.workspaceName == pWorkspace->m_szName /* name matches */ + || (pWorkspace->m_bIsSpecialWorkspace && other.workspaceName.starts_with("special:") && + other.workspaceName.substr(8) == pWorkspace->m_szName) /* special and special:name */ + || (pWorkspace->m_iID > 0 && WORKSPACEIDSTR == other.workspaceName); /* id matches and workspace is numerical */ }); if (IT == m_dWorkspaceRules.end()) return SWorkspaceRule{}; From bb9d0aed5bd11879f5a532e26fc0a91d1a8af714 Mon Sep 17 00:00:00 2001 From: thejch <66577496+thejch@users.noreply.github.com> Date: Fri, 20 Oct 2023 02:53:37 -0700 Subject: [PATCH 098/513] compositor: Fix a lack of a check for workspace equality on same monitors in getInDirection (#3625) * prevent movefocus and movewindow from going into main workspace when in special workspace * compare workspace IDs instead * change comparison and make code more readable --- src/Compositor.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index f02f7c66..704ac64a 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1482,6 +1482,9 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) { if (w.get() == pWindow || !w->m_bIsMapped || w->isHidden() || w->m_bIsFloating || !isWorkspaceVisible(w->m_iWorkspaceID)) continue; + if (pWindow->m_iMonitorID == w->m_iMonitorID && pWindow->m_iWorkspaceID != w->m_iWorkspaceID) + continue; + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID); if (PWORKSPACE->m_bHasFullscreenWindow && !w->m_bIsFullscreen && !w->m_bCreatedOverFullscreen) continue; From bab2f6a664a67dfd0c2f442dbc0134ef7c6e07e2 Mon Sep 17 00:00:00 2001 From: thejch <66577496+thejch@users.noreply.github.com> Date: Fri, 20 Oct 2023 10:01:04 -0700 Subject: [PATCH 099/513] master: fix movewindow across monitors (#3628) --- src/layout/MasterLayout.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index f44e04e3..ebbcc805 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -928,7 +928,16 @@ void CHyprMasterLayout::moveWindowTo(CWindow* pWindow, const std::string& dir) { const auto PWINDOW2 = g_pCompositor->getWindowInDirection(pWindow, dir[0]); - switchWindows(pWindow, PWINDOW2); + if (pWindow->m_iWorkspaceID != PWINDOW2->m_iWorkspaceID) { + // if different monitors, send to monitor + onWindowRemovedTiling(pWindow); + pWindow->moveToWorkspace(PWINDOW2->m_iWorkspaceID); + pWindow->m_iMonitorID = PWINDOW2->m_iMonitorID; + onWindowCreatedTiling(pWindow); + } else { + // if same monitor, switch windows + switchWindows(pWindow, PWINDOW2); + } } void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) { From 7f35f33b4ca16509e127976772db6abd9abf100b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 20 Oct 2023 20:15:41 +0100 Subject: [PATCH 100/513] surface/wayland: conform to small surface requirements do not stretch small surfaces, instead center them if they fit. --- src/Window.cpp | 6 ++++++ src/Window.hpp | 1 + src/events/Windows.cpp | 2 ++ src/helpers/WLSurface.cpp | 17 +++++++++++++++++ src/helpers/WLSurface.hpp | 31 +++++++++++++++++++++++-------- src/managers/XWaylandManager.cpp | 4 ++-- src/render/Renderer.cpp | 25 +++++++++++++++++++++++-- 7 files changed, 74 insertions(+), 12 deletions(-) diff --git a/src/Window.cpp b/src/Window.cpp index 6a83c7fa..af5015d4 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -424,6 +424,7 @@ void CWindow::onUnmap() { void CWindow::onMap() { m_pWLSurface.assign(g_pXWaylandManager->getWindowSurface(this)); + m_pWLSurface.m_pOwner = this; // 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(); @@ -453,6 +454,8 @@ void CWindow::onMap() { hyprListener_unmapWindow.initCallback(m_bIsX11 ? &m_uSurface.xwayland->surface->events.unmap : &m_uSurface.xdg->surface->events.unmap, &Events::listener_unmapWindow, this, "CWindow"); + + m_vReportedSize = m_vPendingReportedSize; } void CWindow::onBorderAngleAnimEnd(void* ptr) { @@ -882,6 +885,9 @@ bool CWindow::opaque() { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID); + if (m_pWLSurface.small() && !m_pWLSurface.m_bFillIgnoreSmall) + return false; + if (PWORKSPACE->m_fAlpha.fl() != 1.f) return false; diff --git a/src/Window.hpp b/src/Window.hpp index dd16fdcb..e9014471 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -203,6 +203,7 @@ class CWindow { // for not spamming the protocols Vector2D m_vReportedPosition; Vector2D m_vReportedSize; + Vector2D m_vPendingReportedSize; // for restoring floating statuses Vector2D m_vLastFloatingSize; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index a77c298f..df8475d2 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -789,6 +789,8 @@ void Events::listener_commitWindow(void* owner, void* data) { if (!PWINDOW->m_bMappedX11 || PWINDOW->isHidden() || (PWINDOW->m_bIsX11 && !PWINDOW->m_bMappedX11)) return; + PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged. + PWINDOW->updateSurfaceOutputs(); g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, diff --git a/src/helpers/WLSurface.cpp b/src/helpers/WLSurface.cpp index 8524c9a5..a34c77a1 100644 --- a/src/helpers/WLSurface.cpp +++ b/src/helpers/WLSurface.cpp @@ -27,12 +27,29 @@ 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 || m_pOwner->m_vReportedSize.y > m_pWLRSurface->current.buffer_height; +} + +Vector2D CWLSurface::correctSmallVec() const { + if (!m_pOwner || !exists() || !small() || m_bFillIgnoreSmall) + return {}; + + return Vector2D{(m_pOwner->m_vReportedSize.x - m_pWLRSurface->current.buffer_width) / 2, (m_pOwner->m_vReportedSize.y - m_pWLRSurface->current.buffer_height) / 2}.clamp( + {}, {INFINITY, INFINITY}) * + (m_pOwner->m_vRealSize.vec() / m_pOwner->m_vReportedSize); +} + void CWLSurface::destroy() { if (!m_pWLRSurface) return; hyprListener_destroy.removeCallback(); m_pWLRSurface->data = nullptr; + m_pOwner = nullptr; if (g_pCompositor->m_pLastFocus == m_pWLRSurface) g_pCompositor->m_pLastFocus = nullptr; diff --git a/src/helpers/WLSurface.hpp b/src/helpers/WLSurface.hpp index c5cdd37f..ee6574de 100644 --- a/src/helpers/WLSurface.hpp +++ b/src/helpers/WLSurface.hpp @@ -1,6 +1,9 @@ #pragma once #include "../defines.hpp" + +class CWindow; + class CWLSurface { public: CWLSurface() = default; @@ -10,20 +13,28 @@ class CWLSurface { void assign(wlr_surface* pSurface); void unassign(); - CWLSurface(const CWLSurface&) = delete; - CWLSurface(CWLSurface&&) = delete; + CWLSurface(const CWLSurface&) = delete; + CWLSurface(CWLSurface&&) = delete; CWLSurface& operator=(const CWLSurface&) = delete; - CWLSurface& operator=(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 - CWLSurface& operator=(wlr_surface* pSurface) { - destroy(); - m_pWLRSurface = pSurface; - init(); + // allow stretching. Useful for plugins. + bool m_bFillIgnoreSmall = false; - return *this; + // if present, means this is a base surface of a window. Cleaned on unassign() + CWindow* m_pOwner = nullptr; + + CWLSurface& operator=(wlr_surface* pSurface) { + destroy(); + m_pWLRSurface = pSurface; + init(); + + return *this; } bool operator==(const CWLSurface& other) const { @@ -38,6 +49,10 @@ class CWLSurface { return exists(); } + static CWLSurface* surfaceFromWlr(wlr_surface* pSurface) { + return (CWLSurface*)pSurface->data; + } + private: wlr_surface* m_pWLRSurface = nullptr; diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 39331e9c..a40647fa 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -163,8 +163,8 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f if (!force && ((pWindow->m_vReportedSize == size && windowPos == pWindow->m_vReportedPosition) || (pWindow->m_vReportedSize == size && !pWindow->m_bIsX11))) return; - pWindow->m_vReportedPosition = windowPos; - pWindow->m_vReportedSize = size; + pWindow->m_vReportedPosition = windowPos; + pWindow->m_vPendingReportedSize = size; pWindow->m_fX11SurfaceScaledBy = 1.f; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index c4daa416..7fe2774b 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -23,9 +23,23 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, RDATA->pMonitor->output, &outputX, &outputY); wlr_box windowBox; - if (RDATA->surface && surface == RDATA->surface) + if (RDATA->surface && surface == RDATA->surface) { windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, RDATA->w, RDATA->h}; - else { // here we clamp to 2, these might be some tiny specks + + // however, if surface buffer w / h < box, we need to adjust them + auto* const PSURFACE = CWLSurface::surfaceFromWlr(surface); + + if (PSURFACE && !PSURFACE->m_bFillIgnoreSmall && PSURFACE->small() /* guarantees m_pOwner */) { + const auto CORRECT = PSURFACE->correctSmallVec(); + + windowBox.x += CORRECT.x; + windowBox.y += CORRECT.y; + + windowBox.width = (double)surface->current.buffer_width * (PSURFACE->m_pOwner->m_vRealSize.vec().x / PSURFACE->m_pOwner->m_vReportedSize.x); + windowBox.height = (double)surface->current.buffer_height * (PSURFACE->m_pOwner->m_vRealSize.vec().y / PSURFACE->m_pOwner->m_vReportedSize.y); + } + + } else { // here we clamp to 2, these might be some tiny specks windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, std::max(surface->current.width, 2), std::max(surface->current.height, 2)}; if (RDATA->pWindow && RDATA->pWindow->m_vRealSize.isBeingAnimated() && RDATA->surface && RDATA->surface != surface && RDATA->squishOversized /* subsurface */) { // adjust subsurfaces to the window @@ -1392,6 +1406,13 @@ void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y, dou if (g_pCompositor->m_bUnsafeState) return; + auto* const PSURFACE = CWLSurface::surfaceFromWlr(pSurface); + if (PSURFACE && PSURFACE->m_pOwner && PSURFACE->small()) { + const auto CORRECTION = PSURFACE->correctSmallVec(); + x += CORRECTION.x; + y += CORRECTION.y; + } + CRegion damageBox; wlr_surface_get_effective_damage(pSurface, damageBox.pixman()); if (scale != 1.0) From 4a79718fe8e4601983797d254cce39960827cb02 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 20 Oct 2023 20:32:47 +0100 Subject: [PATCH 101/513] renderer: fix shimmers when manual resizing --- src/render/Renderer.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 7fe2774b..c153b855 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -30,13 +30,19 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { auto* const PSURFACE = CWLSurface::surfaceFromWlr(surface); if (PSURFACE && !PSURFACE->m_bFillIgnoreSmall && PSURFACE->small() /* guarantees m_pOwner */) { - const auto CORRECT = PSURFACE->correctSmallVec(); + const auto CORRECT = PSURFACE->correctSmallVec(); + const auto INTERACTIVERESIZEINPROGRESS = g_pInputManager->currentlyDraggedWindow == PSURFACE->m_pOwner && g_pInputManager->dragMode == MBIND_RESIZE; - windowBox.x += CORRECT.x; - windowBox.y += CORRECT.y; + if (!INTERACTIVERESIZEINPROGRESS) { + windowBox.x += CORRECT.x; + windowBox.y += CORRECT.y; - windowBox.width = (double)surface->current.buffer_width * (PSURFACE->m_pOwner->m_vRealSize.vec().x / PSURFACE->m_pOwner->m_vReportedSize.x); - windowBox.height = (double)surface->current.buffer_height * (PSURFACE->m_pOwner->m_vRealSize.vec().y / PSURFACE->m_pOwner->m_vReportedSize.y); + windowBox.width = (double)surface->current.buffer_width * (PSURFACE->m_pOwner->m_vRealSize.vec().x / PSURFACE->m_pOwner->m_vReportedSize.x); + windowBox.height = (double)surface->current.buffer_height * (PSURFACE->m_pOwner->m_vRealSize.vec().y / PSURFACE->m_pOwner->m_vReportedSize.y); + } else { + windowBox.width = (double)surface->current.buffer_width; + windowBox.height = (double)surface->current.buffer_height; + } } } else { // here we clamp to 2, these might be some tiny specks @@ -682,7 +688,7 @@ void CHyprRenderer::calculateUVForSurface(CWindow* pWindow, wlr_surface* pSurfac wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom); // ignore X and Y, adjust uv - if (geom.x != 0 || geom.y != 0 || geom.width > pWindow->m_vRealSize.goalv().x || geom.height > pWindow->m_vRealSize.goalv().y) { + if (geom.x != 0 || geom.y != 0 || geom.width > pWindow->m_vRealSize.vec().x || geom.height > pWindow->m_vRealSize.vec().y) { const auto XPERC = (double)geom.x / (double)pSurface->current.width; const auto YPERC = (double)geom.y / (double)pSurface->current.height; const auto WPERC = (double)(geom.x + geom.width) / (double)pSurface->current.width; @@ -692,9 +698,9 @@ void CHyprRenderer::calculateUVForSurface(CWindow* pWindow, wlr_surface* pSurfac uvBR = uvBR - Vector2D(1.0 - WPERC * (uvBR.x - uvTL.x), 1.0 - HPERC * (uvBR.y - uvTL.y)); uvTL = uvTL + TOADDTL; - if (geom.width > pWindow->m_vRealSize.goalv().x || geom.height > pWindow->m_vRealSize.goalv().y) { - uvBR.x = uvBR.x * (pWindow->m_vRealSize.goalv().x / geom.width); - uvBR.y = uvBR.y * (pWindow->m_vRealSize.goalv().y / geom.height); + if (geom.width > pWindow->m_vRealSize.vec().x || geom.height > pWindow->m_vRealSize.vec().y) { + uvBR.x = uvBR.x * (pWindow->m_vRealSize.vec().x / geom.width); + uvBR.y = uvBR.y * (pWindow->m_vRealSize.vec().y / geom.height); } } From af72404259f7a39069d1449bedbc49b3e6ae4fbc Mon Sep 17 00:00:00 2001 From: Roberto Previdi Date: Sat, 21 Oct 2023 03:28:34 +0200 Subject: [PATCH 102/513] hyprctl: add a query for workspace rules (#3630) --- hyprctl/main.cpp | 3 +++ src/debug/HyprCtl.cpp | 60 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index aebc1cbb..77dd0d58 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -29,6 +29,7 @@ commands: monitors workspaces activeworkspace + workspacerules clients activewindow layers @@ -370,6 +371,8 @@ int main(int argc, char** argv) { request(fullRequest); else if (fullRequest.contains("/activeworkspace")) request(fullRequest); + else if (fullRequest.contains("/workspacerules")) + request(fullRequest); else if (fullRequest.contains("/activewindow")) request(fullRequest); else if (fullRequest.contains("/layers")) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index a9b6a190..309954a7 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -229,6 +229,44 @@ static std::string getWorkspaceData(CWorkspace* w, HyprCtl::eHyprCtlOutputFormat } } +static std::string getWorkspaceRuleData(const SWorkspaceRule& r, HyprCtl::eHyprCtlOutputFormat format) { + const auto boolToString = [](const bool b) -> std::string { return b ? "true" : "false"; }; + if (format == HyprCtl::FORMAT_JSON) { + const std::string monitor = r.monitor.empty() ? "" : std::format(",\n \"monitor\": \"{}\"", escapeJSONStrings(r.monitor)); + const std::string default_ = (bool)(r.isDefault) ? std::format(",\n \"default\": {}", boolToString(r.isDefault)) : ""; + const std::string persistent = (bool)(r.isPersistent) ? std::format(",\n \"persistent\": {}", boolToString(r.isPersistent)) : ""; + const std::string gapsIn = (bool)(r.gapsIn) ? std::format(",\n \"gapsIn\": {}", r.gapsIn.value()) : ""; + const std::string gapsOut = (bool)(r.gapsOut) ? std::format(",\n \"gapsOut\": {}", r.gapsOut.value()) : ""; + const std::string borderSize = (bool)(r.borderSize) ? std::format(",\n \"borderSize\": {}", r.borderSize.value()) : ""; + const std::string border = (bool)(r.border) ? std::format(",\n \"border\": {}", boolToString(r.border.value())) : ""; + const std::string rounding = (bool)(r.rounding) ? std::format(",\n \"rounding\": {}", boolToString(r.rounding.value())) : ""; + const std::string decorate = (bool)(r.decorate) ? std::format(",\n \"decorate\": {}", boolToString(r.decorate.value())) : ""; + const std::string shadow = (bool)(r.shadow) ? std::format(",\n \"shadow\": {}", boolToString(r.shadow.value())) : ""; + + std::string result = std::format(R"#({{ + "workspaceString": "{}"{}{}{}{}{}{}{}{} +}})#", + escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, borderSize, border, rounding, decorate, shadow); + + return result; + } else { + const std::string monitor = std::format("\tmonitor: {}\n", r.monitor.empty() ? "" : escapeJSONStrings(r.monitor)); + const std::string default_ = std::format("\tdefault: {}\n", (bool)(r.isDefault) ? boolToString(r.isDefault) : ""); + const std::string persistent = std::format("\tpersistent: {}\n", (bool)(r.isPersistent) ? boolToString(r.isPersistent) : ""); + const std::string gapsIn = std::format("\tgapsIn: {}\n", (bool)(r.gapsIn) ? std::to_string(r.gapsIn.value()) : ""); + const std::string gapsOut = std::format("\tgapsOut: {}\n", (bool)(r.gapsOut) ? std::to_string(r.gapsOut.value()) : ""); + const std::string borderSize = std::format("\tborderSize: {}\n", (bool)(r.borderSize) ? std::to_string(r.borderSize.value()) : ""); + const std::string border = std::format("\tborder: {}\n", (bool)(r.border) ? boolToString(r.border.value()) : ""); + const std::string rounding = std::format("\trounding: {}\n", (bool)(r.rounding) ? boolToString(r.rounding.value()) : ""); + const std::string decorate = std::format("\tdecorate: {}\n", (bool)(r.decorate) ? boolToString(r.decorate.value()) : ""); + const std::string shadow = std::format("\tshadow: {}\n", (bool)(r.shadow) ? boolToString(r.shadow.value()) : ""); + + std::string result = std::format("Workspace rule {}:\n{}{}{}{}{}{}{}{}{}{}\n", escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, + borderSize, border, rounding, decorate, shadow); + + return result; + } +} std::string activeWorkspaceRequest(HyprCtl::eHyprCtlOutputFormat format) { if (!g_pCompositor->m_pLastMonitor) return "unsafe state"; @@ -263,6 +301,26 @@ std::string workspacesRequest(HyprCtl::eHyprCtlOutputFormat format) { return result; } +std::string workspaceRulesRequest(HyprCtl::eHyprCtlOutputFormat format) { + std::string result = ""; + if (format == HyprCtl::FORMAT_JSON) { + result += "["; + for (auto& r : g_pConfigManager->getAllWorkspaceRules()) { + result += getWorkspaceRuleData(r, format); + result += ","; + } + + trimTrailingComma(result); + result += "]"; + } else { + for (auto& r : g_pConfigManager->getAllWorkspaceRules()) { + result += getWorkspaceRuleData(r, format); + } + } + + return result; +} + std::string activeWindowRequest(HyprCtl::eHyprCtlOutputFormat format) { const auto PWINDOW = g_pCompositor->m_pLastWindow; @@ -1259,6 +1317,8 @@ std::string getReply(std::string request) { return monitorsRequest(format); else if (request == "workspaces") return workspacesRequest(format); + else if (request == "workspacerules") + return workspaceRulesRequest(format); else if (request == "activeworkspace") return activeWorkspaceRequest(format); else if (request == "clients") From 92311d260ab25c11adab05678663bdccaff11fa6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 21 Oct 2023 14:15:48 +0100 Subject: [PATCH 103/513] renderer: add transformers --- src/Window.hpp | 5 +++++ src/render/OpenGL.cpp | 21 +++++++++++++++++++++ src/render/OpenGL.hpp | 7 +++++++ src/render/Renderer.cpp | 17 +++++++++++++++++ src/render/Transformer.cpp | 1 + src/render/Transformer.hpp | 13 +++++++++++++ 6 files changed, 64 insertions(+) create mode 100644 src/render/Transformer.cpp create mode 100644 src/render/Transformer.hpp diff --git a/src/Window.hpp b/src/Window.hpp index e9014471..b54ecdbc 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -32,6 +32,8 @@ enum eGroupRules GROUP_OVERRIDE = 1 << 6, // Override other rules }; +class IWindowTransformer; + template class CWindowOverridableVar { public: @@ -290,6 +292,9 @@ class CWindow { SWindowSpecialRenderData m_sSpecialRenderData; SWindowAdditionalConfigData m_sAdditionalConfigData; + // Transformers + std::vector> m_vTransformers; + // for alpha CAnimatedVariable m_fActiveInactiveAlpha; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 29574887..705d92a8 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -128,10 +128,12 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { m_RenderData.pCurrentMonData->primaryFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; m_RenderData.pCurrentMonData->mirrorFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; + m_RenderData.pCurrentMonData->offMainFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; m_RenderData.pCurrentMonData->primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); + m_RenderData.pCurrentMonData->offMainFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); createBGTextureForMonitor(pMonitor); } @@ -149,6 +151,8 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { m_bFakeFrame = fake; + m_RenderData.currentFB = &m_RenderData.pCurrentMonData->primaryFB; + if (m_bReloadScreenShader) { m_bReloadScreenShader = false; applyScreenShader(g_pConfigManager->getString("decoration:screen_shader")); @@ -1892,6 +1896,7 @@ void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) { g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].mirrorSwapFB.release(); g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].monitorMirrorFB.release(); g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].blurFB.release(); + g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].offMainFB.release(); g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].stencilTex.destroyTexture(); g_pHyprOpenGL->m_mMonitorBGTextures[pMonitor].destroyTexture(); g_pHyprOpenGL->m_mMonitorRenderResources.erase(pMonitor); @@ -1914,3 +1919,19 @@ void CHyprOpenGLImpl::setMatrixScaleTranslate(const Vector2D& translate, const f void CHyprOpenGLImpl::restoreMatrix() { memcpy(m_RenderData.projection, m_RenderData.savedProjection, 9 * sizeof(float)); } + +void CHyprOpenGLImpl::bindOffMain() { + m_RenderData.pCurrentMonData->offMainFB.bind(); + clear(CColor(0, 0, 0, 0)); + m_RenderData.currentFB = &m_RenderData.pCurrentMonData->offMainFB; +} + +void CHyprOpenGLImpl::renderOffToMain(CFramebuffer* off) { + wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; + renderTexturePrimitive(off->m_cTex, &monbox); +} + +void CHyprOpenGLImpl::bindBackOnMain() { + m_RenderData.pCurrentMonData->primaryFB.bind(); + m_RenderData.currentFB = &m_RenderData.pCurrentMonData->primaryFB; +} diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 61e8ffdb..0d4b7852 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -13,6 +13,7 @@ #include "Shader.hpp" #include "Texture.hpp" #include "Framebuffer.hpp" +#include "Transformer.hpp" #include "../debug/TracyDefines.hpp" @@ -41,6 +42,7 @@ struct SMonitorRenderData { CFramebuffer primaryFB; CFramebuffer mirrorFB; // these are used for some effects, CFramebuffer mirrorSwapFB; // etc + CFramebuffer offMainFB; CFramebuffer monitorMirrorFB; // used for mirroring outputs @@ -75,6 +77,7 @@ struct SCurrentRenderData { float savedProjection[9]; SMonitorRenderData* pCurrentMonData = nullptr; + CFramebuffer* currentFB = nullptr; CRegion damage; @@ -142,6 +145,10 @@ class CHyprOpenGLImpl { void applyScreenShader(const std::string& path); + void bindOffMain(); + void renderOffToMain(CFramebuffer* off); + void bindBackOnMain(); + SCurrentRenderData m_RenderData; GLint m_iCurrentOutputFb = 0; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index c153b855..255bdf33 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -406,6 +406,12 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* // render window decorations first, if not fullscreen full if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_MAIN) { + + const bool TRANSFORMERSPRESENT = !pWindow->m_vTransformers.empty(); + + if (TRANSFORMERSPRESENT) + g_pHyprOpenGL->bindOffMain(); + if (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL) for (auto& wd : pWindow->m_dWindowDecorations) wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, offset); @@ -443,6 +449,17 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* g_pHyprOpenGL->renderBorder(&windowBox, g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColorPrevious, renderdata.rounding, borderSize, a2); } } + + if (TRANSFORMERSPRESENT) { + + CFramebuffer* last = g_pHyprOpenGL->m_RenderData.currentFB; + for (auto& t : pWindow->m_vTransformers) { + last = t->transform(last); + } + + g_pHyprOpenGL->bindBackOnMain(); + g_pHyprOpenGL->renderOffToMain(last); + } } if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_POPUP) { diff --git a/src/render/Transformer.cpp b/src/render/Transformer.cpp new file mode 100644 index 00000000..f99e2d98 --- /dev/null +++ b/src/render/Transformer.cpp @@ -0,0 +1 @@ +#include "Transformer.hpp" \ No newline at end of file diff --git a/src/render/Transformer.hpp b/src/render/Transformer.hpp new file mode 100644 index 00000000..62eb3362 --- /dev/null +++ b/src/render/Transformer.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "Framebuffer.hpp" + +// A window transformer can be attached to a window. +// If any is attached, Hyprland will render the window to a separate fb, then call the transform() func with it, +// and finally render it back to the main fb after all transformers pass. +class IWindowTransformer { + public: + // called by Hyprland. For more data about what is being rendered, inspect render data. + // returns the out fb. + virtual CFramebuffer* transform(CFramebuffer* in) = 0; +}; \ No newline at end of file From c6233a790fed3d9a3100e16a73143700846928a2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 21 Oct 2023 14:20:06 +0100 Subject: [PATCH 104/513] renderer: avoid drawing invisibly small surfaces in renderSurface --- src/render/Renderer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 255bdf33..73f289c2 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -61,6 +61,9 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { windowBox.height = RDATA->h - y; } + if (windowBox.width <= 1 || windowBox.height <= 1) + return; // invisible + g_pHyprRenderer->calculateUVForSurface(RDATA->pWindow, surface, RDATA->squishOversized); scaleBox(&windowBox, RDATA->pMonitor->scale); From a61eb7694df25a75f45502ed64b1536fda370c1d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 21 Oct 2023 14:52:43 +0100 Subject: [PATCH 105/513] hooksystem: add callbackinfo struct and cancellable events --- example/examplePlugin/main.cpp | 4 ++-- src/SharedDefs.hpp | 4 ++++ src/debug/HyprNotificationOverlay.cpp | 2 +- src/hyprerror/HyprError.cpp | 4 ++-- src/managers/HookSystemManager.cpp | 6 +++--- src/managers/HookSystemManager.hpp | 17 ++++++++++++++--- src/managers/KeybindManager.cpp | 2 +- src/managers/input/InputManager.cpp | 10 +++++----- src/managers/input/InputMethodRelay.cpp | 2 +- src/plugins/PluginAPI.hpp | 2 +- src/protocols/Screencopy.cpp | 2 +- src/protocols/XDGOutput.cpp | 6 +++--- src/render/OpenGL.cpp | 2 +- 13 files changed, 39 insertions(+), 24 deletions(-) diff --git a/example/examplePlugin/main.cpp b/example/examplePlugin/main.cpp index 560af387..f2cd1075 100644 --- a/example/examplePlugin/main.cpp +++ b/example/examplePlugin/main.cpp @@ -58,8 +58,8 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { HyprlandAPI::addNotification(PHANDLE, "Hello World from an example plugin!", CColor{0.f, 1.f, 1.f, 1.f}, 5000); - HyprlandAPI::registerCallbackDynamic(PHANDLE, "activeWindow", [&](void* self, std::any data) { onActiveWindowChange(self, data); }); - HyprlandAPI::registerCallbackDynamic(PHANDLE, "openWindow", [&](void* self, std::any data) { onNewWindow(self, data); }); + HyprlandAPI::registerCallbackDynamic(PHANDLE, "activeWindow", [&](void* self, SCallbackInfo& info, std::any data) { onActiveWindowChange(self, data); }); + HyprlandAPI::registerCallbackDynamic(PHANDLE, "openWindow", [&](void* self, SCallbackInfo& info, std::any data) { onNewWindow(self, data); }); g_pCustomLayout = std::make_unique(); diff --git a/src/SharedDefs.hpp b/src/SharedDefs.hpp index 53a9850a..068d61f6 100644 --- a/src/SharedDefs.hpp +++ b/src/SharedDefs.hpp @@ -22,4 +22,8 @@ enum eRenderStage RENDER_POST_MIRROR, /* After rendering a mirror */ RENDER_PRE_WINDOW, /* Before rendering a window (any pass) Note some windows (e.g. tiled) may have 2 passes (main & popup) */ RENDER_POST_WINDOW, /* After rendering a window (any pass) */ +}; + +struct SCallbackInfo { + bool cancelled = false; /* on cancellable events, will cancel the event. */ }; \ No newline at end of file diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index b4ed38c3..f82ca9bb 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -3,7 +3,7 @@ #include CHyprNotificationOverlay::CHyprNotificationOverlay() { - g_pHookSystem->hookDynamic("focusedMon", [&](void* self, std::any param) { + g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) { if (m_dNotifications.size() == 0) return; diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index b72f0589..4f916139 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -5,7 +5,7 @@ CHyprError::CHyprError() { m_fFadeOpacity.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), nullptr, AVARDAMAGE_NONE); m_fFadeOpacity.registerVar(); - g_pHookSystem->hookDynamic("focusedMon", [&](void* self, std::any param) { + g_pHookSystem->hookDynamic("focusedMon", [&](void* self, SCallbackInfo& info, std::any param) { if (!m_bIsCreated) return; @@ -13,7 +13,7 @@ CHyprError::CHyprError() { m_bMonitorChanged = true; }); - g_pHookSystem->hookDynamic("preRender", [&](void* self, std::any param) { + g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any param) { if (!m_bIsCreated) return; diff --git a/src/managers/HookSystemManager.cpp b/src/managers/HookSystemManager.cpp index 567286d6..48c300cb 100644 --- a/src/managers/HookSystemManager.cpp +++ b/src/managers/HookSystemManager.cpp @@ -26,7 +26,7 @@ void CHookSystemManager::unhook(HOOK_CALLBACK_FN* fn) { } } -void CHookSystemManager::emit(const std::vector* callbacks, std::any data) { +void CHookSystemManager::emit(const std::vector* callbacks, SCallbackInfo& info, std::any data) { if (callbacks->empty()) return; @@ -38,7 +38,7 @@ void CHookSystemManager::emit(const std::vector* callbacks, std: if (!cb.handle) { // we don't guard hl hooks - (*cb.fn)(cb.fn, data); + (*cb.fn)(cb.fn, info, data); continue; } @@ -49,7 +49,7 @@ void CHookSystemManager::emit(const std::vector* callbacks, std: try { if (!setjmp(m_jbHookFaultJumpBuf)) - (*cb.fn)(cb.fn, data); + (*cb.fn)(cb.fn, info, data); else { // this module crashed. throw std::exception(); diff --git a/src/managers/HookSystemManager.hpp b/src/managers/HookSystemManager.hpp index 66edd1c0..ca8e9006 100644 --- a/src/managers/HookSystemManager.hpp +++ b/src/managers/HookSystemManager.hpp @@ -12,7 +12,8 @@ #include "../plugins/PluginAPI.hpp" // global typedef for hooked functions. Passes itself as a ptr when called, and `data` additionally. -typedef std::function HOOK_CALLBACK_FN; + +typedef std::function HOOK_CALLBACK_FN; struct SCallbackFNPtr { HOOK_CALLBACK_FN* fn = nullptr; @@ -22,7 +23,17 @@ struct SCallbackFNPtr { #define EMIT_HOOK_EVENT(name, param) \ { \ static auto* const PEVENTVEC = g_pHookSystem->getVecForEvent(name); \ - g_pHookSystem->emit(PEVENTVEC, param); \ + SCallbackInfo info; \ + g_pHookSystem->emit(PEVENTVEC, info, param); \ + } + +#define EMIT_HOOK_EVENT_CANCELLABLE(name, param) \ + { \ + static auto* const PEVENTVEC = g_pHookSystem->getVecForEvent(name); \ + SCallbackInfo info; \ + g_pHookSystem->emit(PEVENTVEC, info, param); \ + if (info.cancelled) \ + return; \ } class CHookSystemManager { @@ -34,7 +45,7 @@ class CHookSystemManager { void hookStatic(const std::string& event, HOOK_CALLBACK_FN* fn, HANDLE handle = nullptr); void unhook(HOOK_CALLBACK_FN* fn); - void emit(const std::vector* callbacks, std::any data = 0); + void emit(const std::vector* callbacks, SCallbackInfo& info, std::any data = 0); std::vector* getVecForEvent(const std::string& event); bool m_bCurrentEventPlugin = false; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 7e0b7620..321409cc 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -77,7 +77,7 @@ CKeybindManager::CKeybindManager() { m_tScrollTimer.reset(); - g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, std::any param) { + g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, SCallbackInfo& info, std::any param) { // clear cuz realloc'd m_pActiveKeybind = nullptr; m_vPressedSpecialBinds.clear(); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index ab5be4bc..1d8b5135 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -97,11 +97,11 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (MOUSECOORDSFLOORED == m_vLastCursorPosFloored && !refocus) return; + EMIT_HOOK_EVENT_CANCELLABLE("mouseMove", MOUSECOORDSFLOORED); + if (time) g_pCompositor->notifyIdleActivity(); - EMIT_HOOK_EVENT("mouseMove", MOUSECOORDSFLOORED); - m_vLastCursorPosFloored = MOUSECOORDSFLOORED; const auto PMONITOR = g_pCompositor->getMonitorFromCursor(); @@ -422,9 +422,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { } void CInputManager::onMouseButton(wlr_pointer_button_event* e) { - g_pCompositor->notifyIdleActivity(); + EMIT_HOOK_EVENT_CANCELLABLE("mouseButton", e); - EMIT_HOOK_EVENT("mouseButton", e); + g_pCompositor->notifyIdleActivity(); m_tmrLastCursorMovement.reset(); @@ -1580,7 +1580,7 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) { wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; eBorderIconDirection direction = BORDERICON_NONE; wlr_box boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE), - box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; + box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; if (!wlr_box_contains_point(&boxFullGrabInput, mouseCoords.x, mouseCoords.y) || (!m_lCurrentlyHeldButtons.empty() && !currentlyDraggedWindow)) { direction = BORDERICON_NONE; diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index 58ad2a2d..4af17096 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -3,7 +3,7 @@ #include "../../Compositor.hpp" CInputMethodRelay::CInputMethodRelay() { - g_pHookSystem->hookDynamic("keyboardFocus", [&](void* self, std::any param) { onKeyboardFocus(std::any_cast(param)); }); + g_pHookSystem->hookDynamic("keyboardFocus", [&](void* self, SCallbackInfo& info, std::any param) { onKeyboardFocus(std::any_cast(param)); }); } void CInputMethodRelay::onNewIME(wlr_input_method_v2* pIME) { diff --git a/src/plugins/PluginAPI.hpp b/src/plugins/PluginAPI.hpp index a406f2e6..36cdbe63 100644 --- a/src/plugins/PluginAPI.hpp +++ b/src/plugins/PluginAPI.hpp @@ -29,7 +29,7 @@ Feel like the API is missing something you'd like to use in your plugin? Open an #include #include -typedef std::function HOOK_CALLBACK_FN; +typedef std::function HOOK_CALLBACK_FN; typedef struct { std::string name; std::string description; diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 9839b660..a84f853f 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -119,7 +119,7 @@ CScreencopyClient::~CScreencopyClient() { CScreencopyClient::CScreencopyClient() { lastMeasure.reset(); lastFrame.reset(); - tickCallback = g_pHookSystem->hookDynamic("tick", [&](void* self, std::any data) { onTick(); }); + tickCallback = g_pHookSystem->hookDynamic("tick", [&](void* self, SCallbackInfo& info, std::any data) { onTick(); }); } void CScreencopyClient::onTick() { diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index 94839e20..2ef0c3a6 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -58,9 +58,9 @@ void CXDGOutputProtocol::bindManager(wl_client* client, void* data, uint32_t ver } CXDGOutputProtocol::CXDGOutputProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { - g_pHookSystem->hookDynamic("monitorLayoutChanged", [this](void* self, std::any param) { this->updateAllOutputs(); }); - g_pHookSystem->hookDynamic("configReloaded", [this](void* self, std::any param) { this->updateAllOutputs(); }); - g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, std::any param) { + g_pHookSystem->hookDynamic("monitorLayoutChanged", [this](void* self, SCallbackInfo& info, std::any param) { this->updateAllOutputs(); }); + g_pHookSystem->hookDynamic("configReloaded", [this](void* self, SCallbackInfo& info, std::any param) { this->updateAllOutputs(); }); + g_pHookSystem->hookDynamic("monitorRemoved", [this](void* self, SCallbackInfo& info, std::any param) { const auto PMONITOR = std::any_cast(param); std::erase_if(m_vXDGOutputs, [&](const auto& other) { const auto REMOVE = other->monitor == PMONITOR; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 705d92a8..4a5b70dd 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -37,7 +37,7 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() { Debug::log(WARN, "!RENDERER: Using the legacy GLES2 renderer!"); #endif - g_pHookSystem->hookDynamic("preRender", [&](void* self, std::any data) { preRender(std::any_cast(data)); }); + g_pHookSystem->hookDynamic("preRender", [&](void* self, SCallbackInfo& info, std::any data) { preRender(std::any_cast(data)); }); RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT), "Couldn't unset current EGL!"); From 95db9108e55ee1498bb23600e5f0a909d7685a4a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 21 Oct 2023 19:25:44 +0100 Subject: [PATCH 106/513] transformers: allow modifying renderdata pre-pass --- src/render/Renderer.cpp | 7 ++++++- src/render/Transformer.cpp | 6 +++++- src/render/Transformer.hpp | 7 +++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 73f289c2..1757cba7 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -412,9 +412,14 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* const bool TRANSFORMERSPRESENT = !pWindow->m_vTransformers.empty(); - if (TRANSFORMERSPRESENT) + if (TRANSFORMERSPRESENT) { g_pHyprOpenGL->bindOffMain(); + for (auto& t : pWindow->m_vTransformers) { + t->preWindowRender(&renderdata); + } + } + if (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL) for (auto& wd : pWindow->m_dWindowDecorations) wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, offset); diff --git a/src/render/Transformer.cpp b/src/render/Transformer.cpp index f99e2d98..c6989d2c 100644 --- a/src/render/Transformer.cpp +++ b/src/render/Transformer.cpp @@ -1 +1,5 @@ -#include "Transformer.hpp" \ No newline at end of file +#include "Transformer.hpp" + +void IWindowTransformer::preWindowRender(SRenderData* pRenderData) { + ; +} \ No newline at end of file diff --git a/src/render/Transformer.hpp b/src/render/Transformer.hpp index 62eb3362..90fdeba9 100644 --- a/src/render/Transformer.hpp +++ b/src/render/Transformer.hpp @@ -2,12 +2,19 @@ #include "Framebuffer.hpp" +struct SRenderData; + // A window transformer can be attached to a window. // If any is attached, Hyprland will render the window to a separate fb, then call the transform() func with it, // and finally render it back to the main fb after all transformers pass. +// +// Worth noting transformers for now only affect the main pass (not popups) class IWindowTransformer { public: // called by Hyprland. For more data about what is being rendered, inspect render data. // returns the out fb. virtual CFramebuffer* transform(CFramebuffer* in) = 0; + + // called by Hyprland before a window main pass is started. + virtual void preWindowRender(SRenderData* pRenderData); }; \ No newline at end of file From d0367d8560653eafdcce14778b2f44e6c6ddf707 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 21 Oct 2023 19:51:14 +0100 Subject: [PATCH 107/513] renderer: use preOffset pos instead of offset offset is not passed to transformers, so if they change pos, decos will be in the wrong place --- src/render/Renderer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 1757cba7..e0966302 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -379,8 +379,10 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* } // clip box for animated offsets - Vector2D offset; + const Vector2D PREOFFSETPOS = {renderdata.x, renderdata.y}; if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bPinned) { + Vector2D offset; + if (PWORKSPACE->m_vRenderOffset.vec().x != 0) { const auto PWSMON = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); const auto PROGRESS = PWORKSPACE->m_vRenderOffset.vec().x / PWSMON->vecSize.x; @@ -422,7 +424,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* if (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL) for (auto& wd : pWindow->m_dWindowDecorations) - wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, offset); + wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, Vector2D{renderdata.x, renderdata.y} - PREOFFSETPOS); static auto* const PXWLUSENN = &g_pConfigManager->getConfigValuePtr("xwayland:use_nearest_neighbor")->intValue; if (pWindow->m_bIsX11 && *PXWLUSENN) From edb26e03063d8001f69712a6aa82d30610589bcb Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 22 Oct 2023 12:25:26 +0100 Subject: [PATCH 108/513] cmake: remove old definitions from cmakelists --- CMakeLists.txt | 8 -------- 1 file changed, 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 709a8eaf..228e40c4 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -183,14 +183,6 @@ else() endif() endif() -target_compile_definitions(Hyprland - PRIVATE - "GIT_COMMIT_HASH=\"${GIT_COMMIT_HASH}\"" - "GIT_BRANCH=\"${GIT_BRANCH}\"" - "GIT_COMMIT_MESSAGE=\"${GIT_COMMIT_MESSAGE}\"" - "GIT_DIRTY=\"${GIT_DIRTY}\"" - "GIT_TAG=\"${GIT_TAG}\"") - set(CPACK_PROJECT_NAME ${PROJECT_NAME}) set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) include(CPack) From 59f27e7f570170783ac01fb46a0ff90e14de53e6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 22 Oct 2023 16:58:06 +0100 Subject: [PATCH 109/513] compositor: send preferred scale and transform events to surfaces fixes #3635 --- src/Compositor.cpp | 9 +++++++++ src/Compositor.hpp | 2 ++ src/Window.cpp | 3 ++- src/events/Layers.cpp | 6 ++++-- src/events/Popups.cpp | 6 ++++-- src/events/Windows.cpp | 3 ++- 6 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 704ac64a..cc9d4244 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2677,3 +2677,12 @@ void CCompositor::leaveUnsafeState() { m_pUnsafeOutput = nullptr; } + +void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scale) { + g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(pSurface, scale); + wlr_surface_set_preferred_buffer_scale(pSurface, scale); +} + +void CCompositor::setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform) { + wlr_surface_set_preferred_buffer_transform(pSurface, transform); +} \ No newline at end of file diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 86460211..fdbac136 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -207,6 +207,8 @@ class CCompositor { void arrangeMonitors(); void enterUnsafeState(); void leaveUnsafeState(); + void setPreferredScaleForSurface(wlr_surface* pSurface, double scale); + void setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform); std::string explicitConfigPath; diff --git a/src/Window.cpp b/src/Window.cpp index af5015d4..65619585 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -325,7 +325,8 @@ void CWindow::updateSurfaceOutputs() { m_pWLSurface.wlr(), [](wlr_surface* surf, int x, int y, void* data) { const auto PMONITOR = g_pCompositor->getMonitorFromID(((CWindow*)data)->m_iMonitorID); - g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(surf, PMONITOR ? PMONITOR->scale : 1.f); + g_pCompositor->setPreferredScaleForSurface(surf, PMONITOR ? PMONITOR->scale : 1.f); + g_pCompositor->setPreferredTransformForSurface(surf, PMONITOR->transform); }, this); } diff --git a/src/events/Layers.cpp b/src/events/Layers.cpp index cb99d0b3..a14ae3f9 100644 --- a/src/events/Layers.cpp +++ b/src/events/Layers.cpp @@ -171,7 +171,8 @@ void Events::listener_mapLayerSurface(void* owner, void* data) { g_pEventManager->postEvent(SHyprIPCEvent{"openlayer", std::string(layersurface->layerSurface->_namespace ? layersurface->layerSurface->_namespace : "")}); EMIT_HOOK_EVENT("openLayer", layersurface); - g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(layersurface->layerSurface->surface, PMONITOR->scale); + g_pCompositor->setPreferredScaleForSurface(layersurface->layerSurface->surface, PMONITOR->scale); + g_pCompositor->setPreferredTransformForSurface(layersurface->layerSurface->surface, PMONITOR->transform); } void Events::listener_unmapLayerSurface(void* owner, void* data) { @@ -342,5 +343,6 @@ void Events::listener_commitLayerSurface(void* owner, void* data) { g_pHyprRenderer->damageSurface(layersurface->layerSurface->surface, layersurface->position.x, layersurface->position.y); - g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(layersurface->layerSurface->surface, PMONITOR->scale); + g_pCompositor->setPreferredScaleForSurface(layersurface->layerSurface->surface, PMONITOR->scale); + g_pCompositor->setPreferredTransformForSurface(layersurface->layerSurface->surface, PMONITOR->transform); } diff --git a/src/events/Popups.cpp b/src/events/Popups.cpp index b8d1dffa..570963d9 100644 --- a/src/events/Popups.cpp +++ b/src/events/Popups.cpp @@ -164,8 +164,10 @@ void Events::listener_mapPopupXDG(void* owner, void* data) { g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2); - if (PPOPUP->monitor) - g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(PPOPUP->popup->base->surface, PPOPUP->monitor->scale); + if (PPOPUP->monitor) { + g_pCompositor->setPreferredScaleForSurface(PPOPUP->popup->base->surface, PPOPUP->monitor->scale); + g_pCompositor->setPreferredTransformForSurface(PPOPUP->popup->base->surface, PPOPUP->monitor->transform); + } Debug::log(LOG, "XDG Popup got assigned a surfaceTreeNode {:x}", (uintptr_t)PPOPUP->pSurfaceTree); } diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index df8475d2..89b327b0 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -646,7 +646,8 @@ void Events::listener_mapWindow(void* owner, void* data) { if (PWORKSPACE->m_bHasFullscreenWindow && !PWINDOW->m_bIsFullscreen && !PWINDOW->m_bIsFloating) PWINDOW->m_fAlpha.setValueAndWarp(0.f); - g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale); + g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale); + g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform); } void Events::listener_unmapWindow(void* owner, void* data) { From b135bd6cd4c27a9fd94dfa084e75188463c2eb3b Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Sun, 22 Oct 2023 19:11:03 -0300 Subject: [PATCH 110/513] workspacerules: Add new optional "default command" for auto-launching apps on new workspaces (#3559) --- src/Compositor.cpp | 33 ++++++++++++++++---------- src/config/ConfigManager.cpp | 8 ++++++- src/config/ConfigManager.hpp | 27 +++++++++++---------- src/helpers/MiscFunctions.cpp | 42 +++++++++++++++++++++++++++++++-- src/helpers/MiscFunctions.hpp | 2 ++ src/helpers/VarList.hpp | 10 ++++++++ src/helpers/Workspace.hpp | 6 +++-- src/managers/KeybindManager.cpp | 2 ++ 8 files changed, 100 insertions(+), 30 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index cc9d4244..20656243 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1194,24 +1194,33 @@ void CCompositor::sanityCheckWorkspaces() { continue; } - const auto WINDOWSONWORKSPACE = getWindowsOnWorkspace((*it)->m_iID); + const auto& WORKSPACE = *it; + const auto WINDOWSONWORKSPACE = getWindowsOnWorkspace(WORKSPACE->m_iID); - if ((WINDOWSONWORKSPACE == 0 && !isWorkspaceVisible((*it)->m_iID))) { + if (WINDOWSONWORKSPACE == 0) { + if (!isWorkspaceVisible(WORKSPACE->m_iID)) { - if ((*it)->m_bIsSpecialWorkspace) { - if ((*it)->m_fAlpha.fl() > 0.f /* don't abruptly end the fadeout */) { - ++it; - continue; + if (WORKSPACE->m_bIsSpecialWorkspace) { + if (WORKSPACE->m_fAlpha.fl() > 0.f /* don't abruptly end the fadeout */) { + ++it; + continue; + } + + const auto PMONITOR = getMonitorFromID(WORKSPACE->m_iMonitorID); + + if (PMONITOR && PMONITOR->specialWorkspaceID == WORKSPACE->m_iID) + PMONITOR->setSpecialWorkspace(nullptr); } - const auto PMONITOR = getMonitorFromID((*it)->m_iMonitorID); - - if (PMONITOR && PMONITOR->specialWorkspaceID == (*it)->m_iID) - PMONITOR->setSpecialWorkspace(nullptr); + it = m_vWorkspaces.erase(it); + continue; } + if (!WORKSPACE->m_bOnCreatedEmptyExecuted) { + if (auto cmd = WORKSPACERULE.onCreatedEmptyRunCmd) + g_pKeybindManager->spawn(*cmd); - it = m_vWorkspaces.erase(it); - continue; + WORKSPACE->m_bOnCreatedEmptyExecuted = true; + } } ++it; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f0961aa0..2ecac5c9 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2,6 +2,7 @@ #include "../managers/KeybindManager.hpp" #include +#include #include #include #include @@ -1176,7 +1177,10 @@ void CConfigManager::handleWorkspaceRules(const std::string& command, const std: rules = value.substr(WORKSPACE_DELIM + 1); } - auto assignRule = [&](std::string rule) { + const static std::string ruleOnCreatedEmtpy = "on-created-empty:"; + const static int ruleOnCreatedEmtpyLen = ruleOnCreatedEmtpy.length(); + + auto assignRule = [&](std::string rule) { size_t delim = std::string::npos; if ((delim = rule.find("gapsin:")) != std::string::npos) wsRule.gapsIn = std::stoi(rule.substr(delim + 7)); @@ -1198,6 +1202,8 @@ void CConfigManager::handleWorkspaceRules(const std::string& command, const std: wsRule.isDefault = configStringToInt(rule.substr(delim + 8)); else if ((delim = rule.find("persistent:")) != std::string::npos) wsRule.isPersistent = configStringToInt(rule.substr(delim + 11)); + else if ((delim = rule.find(ruleOnCreatedEmtpy)) != std::string::npos) + wsRule.onCreatedEmptyRunCmd = cleanCmdForWorkspace(name, rule.substr(delim + ruleOnCreatedEmtpyLen)); }; size_t pos = 0; diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index e637979d..c6c726bf 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -36,19 +36,20 @@ struct SConfigValue { }; struct SWorkspaceRule { - std::string monitor = ""; - std::string workspaceString = ""; - std::string workspaceName = ""; - int workspaceId = -1; - bool isDefault = false; - bool isPersistent = false; - std::optional gapsIn; - std::optional gapsOut; - std::optional borderSize; - std::optional border; - std::optional rounding; - std::optional decorate; - std::optional shadow; + std::string monitor = ""; + std::string workspaceString = ""; + std::string workspaceName = ""; + int workspaceId = -1; + bool isDefault = false; + bool isPersistent = false; + std::optional gapsIn; + std::optional gapsOut; + std::optional borderSize; + std::optional border; + std::optional rounding; + std::optional decorate; + std::optional shadow; + std::optional onCreatedEmptyRunCmd; }; struct SMonitorAdditionalReservedArea { diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index b3236725..3cce73d2 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -2,6 +2,7 @@ #include "../defines.hpp" #include #include "../Compositor.hpp" +#include #include #include #include @@ -503,6 +504,43 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { return result; } +std::optional cleanCmdForWorkspace(const std::string& inWorkspaceName, std::string dirtyCmd) { + + std::string cmd = removeBeginEndSpacesTabs(dirtyCmd); + + if (!cmd.empty()) { + std::string rules; + const std::string workspaceRule = "workspace " + inWorkspaceName; + + if (cmd[0] == '[') { + const int closingBracketIdx = cmd.find_last_of(']'); + auto tmpRules = cmd.substr(1, closingBracketIdx - 1); + cmd = cmd.substr(closingBracketIdx + 1); + + auto rulesList = CVarList(tmpRules, 0, ';'); + + bool hadWorkspaceRule = false; + rulesList.map([&](std::string& rule) { + if (rule.find("workspace") == 0) { + rule = workspaceRule; + hadWorkspaceRule = true; + } + }); + + if (!hadWorkspaceRule) + rulesList.append(workspaceRule); + + rules = "[" + rulesList.join(";") + "]"; + } else { + rules = "[" + workspaceRule + "]"; + } + + return std::optional(rules + " " + cmd); + } + + return std::nullopt; +} + float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2) { const float DX = std::max({0.0, p1.x - vec.x, vec.x - p2.x}); const float DY = std::max({0.0, p1.y - vec.y, vec.y - p2.y}); @@ -594,8 +632,8 @@ int64_t getPPIDof(int64_t pid) { return 0; #else - std::string dir = "/proc/" + std::to_string(pid) + "/status"; - FILE* infile; + std::string dir = "/proc/" + std::to_string(pid) + "/status"; + FILE* infile; infile = fopen(dir.c_str(), "r"); if (!infile) diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 429f381f..d489a0cd 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -20,6 +21,7 @@ std::string removeBeginEndSpacesTabs(std::string); bool isNumber(const std::string&, bool allowfloat = false); bool isDirection(const std::string&); int getWorkspaceIDFromString(const std::string&, std::string&); +std::optional cleanCmdForWorkspace(const std::string&, std::string); float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2); void logSystemInfo(); std::string execAndGet(const char*); diff --git a/src/helpers/VarList.hpp b/src/helpers/VarList.hpp index 60e9a551..8f33f166 100644 --- a/src/helpers/VarList.hpp +++ b/src/helpers/VarList.hpp @@ -1,4 +1,5 @@ #pragma once +#include #include #include #include "../macros.hpp" @@ -20,6 +21,15 @@ class CVarList { std::string join(const std::string& joiner, size_t from = 0, size_t to = 0) const; + void map(std::function func) { + for (auto& s : m_vArgs) + func(s); + } + + void append(const std::string arg) { + m_vArgs.emplace_back(arg); + } + std::string operator[](const size_t& idx) const { if (idx >= m_vArgs.size()) return ""; diff --git a/src/helpers/Workspace.hpp b/src/helpers/Workspace.hpp index cbdbc07a..a0bbb815 100644 --- a/src/helpers/Workspace.hpp +++ b/src/helpers/Workspace.hpp @@ -4,8 +4,7 @@ #include #include "../defines.hpp" -enum eFullscreenMode : int8_t -{ +enum eFullscreenMode : int8_t { FULLSCREEN_INVALID = -1, FULLSCREEN_FULL = 0, FULLSCREEN_MAXIMIZED @@ -53,6 +52,9 @@ class CWorkspace { // 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); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 321409cc..72e7f24e 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1,5 +1,7 @@ #include "KeybindManager.hpp" #include "../render/decorations/CHyprGroupBarDecoration.hpp" +#include "debug/Log.hpp" +#include "helpers/VarList.hpp" #include From 98059b52d759965916e0185ca35a01cc20a797b6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 22 Oct 2023 23:32:37 +0100 Subject: [PATCH 111/513] layershell: support ON_DEMAND keyboard mode fixes #2264 --- src/events/Layers.cpp | 2 +- src/managers/input/InputManager.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/events/Layers.cpp b/src/events/Layers.cpp index a14ae3f9..5762e21a 100644 --- a/src/events/Layers.cpp +++ b/src/events/Layers.cpp @@ -142,7 +142,7 @@ void Events::listener_mapLayerSurface(void* owner, void* data) { wlr_surface_send_enter(layersurface->layerSurface->surface, layersurface->layerSurface->output); - const bool GRABSFOCUS = layersurface->layerSurface->current.keyboard_interactive && + const bool GRABSFOCUS = layersurface->layerSurface->current.keyboard_interactive != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE && // don't focus if constrained (!g_pCompositor->m_sSeat.mouse || !g_pCompositor->m_sSeat.mouse->currentConstraint); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 1d8b5135..3fe892c1 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -335,12 +335,11 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { bool allowKeyboardRefocus = true; - if (*PHOGFOCUS && !refocus && g_pCompositor->m_pLastFocus) { + if (!refocus && g_pCompositor->m_pLastFocus) { const auto PLS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus); - if (PLS && PLS->layerSurface->current.keyboard_interactive) { + if (PLS && PLS->layerSurface->current.keyboard_interactive == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) allowKeyboardRefocus = false; - } } // set the values for use @@ -407,7 +406,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { } if (pFoundLayerSurface && - (pFoundLayerSurface->layerSurface->current.keyboard_interactive || (pFoundLayerSurface->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP && !g_pCompositor->m_pLastWindow)) && + (pFoundLayerSurface->layerSurface->current.keyboard_interactive != ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_NONE || + (pFoundLayerSurface->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP && !g_pCompositor->m_pLastWindow)) && FOLLOWMOUSE != 3 && allowKeyboardRefocus) { g_pCompositor->focusSurface(foundSurface); } From 015664eb4cde5ab93cfacbfd8c2e831eeb876634 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 23 Oct 2023 00:53:33 +0100 Subject: [PATCH 112/513] compositor: do not process fullscreen events in unsafe --- src/Compositor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 20656243..1163acca 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2170,7 +2170,7 @@ void CCompositor::updateFullscreenFadeOnWorkspace(CWorkspace* pWorkspace) { } void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode mode) { - if (!windowValidMapped(pWindow)) + if (!windowValidMapped(pWindow) || g_pCompositor->m_bUnsafeState) return; if (pWindow->m_bPinned) { From 2f6729f557fedc65575919e0227e8a5c5b761e51 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 24 Oct 2023 00:50:45 +0100 Subject: [PATCH 113/513] example: add special workspace to default config --- example/hyprland.conf | 4 ++++ src/config/defaultConfig.hpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/example/hyprland.conf b/example/hyprland.conf index 01dbfda9..698335ea 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -163,6 +163,10 @@ bind = $mainMod SHIFT, 8, movetoworkspace, 8 bind = $mainMod SHIFT, 9, movetoworkspace, 9 bind = $mainMod SHIFT, 0, movetoworkspace, 10 +# Example special workspace (scratchpad) +bind = $mainMod, S, togglespecialworkspace, magic +bind = $mainMod SHIFT, S, movetoworkspace, special:magic + # Scroll through existing workspaces with mainMod + scroll bind = $mainMod, mouse_down, workspace, e+1 bind = $mainMod, mouse_up, workspace, e-1 diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 5e7588fc..e190fb3f 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -172,6 +172,10 @@ bind = $mainMod SHIFT, 8, movetoworkspace, 8 bind = $mainMod SHIFT, 9, movetoworkspace, 9 bind = $mainMod SHIFT, 0, movetoworkspace, 10 +# Example special workspace (scratchpad) +bind = $mainMod, S, togglespecialworkspace, magic +bind = $mainMod SHIFT, S, movetoworkspace, special:magic + # Scroll through existing workspaces with mainMod + scroll bind = $mainMod, mouse_down, workspace, e+1 bind = $mainMod, mouse_up, workspace, e-1 From 616ff343b75424a835e5c8ada929943284913910 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 24 Oct 2023 00:53:59 +0100 Subject: [PATCH 114/513] input: fix warn --- src/managers/input/InputManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 3fe892c1..5231a9a7 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -65,7 +65,6 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { static auto* const PMOUSEREFOCUS = &g_pConfigManager->getConfigValuePtr("input:mouse_refocus")->intValue; static auto* const PMOUSEDPMS = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_enables_dpms")->intValue; static auto* const PFOLLOWONDND = &g_pConfigManager->getConfigValuePtr("misc:always_follow_on_dnd")->intValue; - static auto* const PHOGFOCUS = &g_pConfigManager->getConfigValuePtr("misc:layers_hog_keyboard_focus")->intValue; static auto* const PFLOATBEHAVIOR = &g_pConfigManager->getConfigValuePtr("input:float_switch_override_focus")->intValue; static auto* const PMOUSEFOCUSMON = &g_pConfigManager->getConfigValuePtr("misc:mouse_move_focuses_monitor")->intValue; static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue; From aeb8c8fc7087879c85397f39c565246bc2e193b6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 24 Oct 2023 00:58:44 +0100 Subject: [PATCH 115/513] internal: honor close_special_on_empty on moveToWorkspace fixes #3602 --- src/Window.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Window.cpp b/src/Window.cpp index 65619585..ca9625ad 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -335,6 +335,10 @@ void CWindow::moveToWorkspace(int workspaceID) { if (m_iWorkspaceID == workspaceID) return; + static auto* const PCLOSEONLASTSPECIAL = &g_pConfigManager->getConfigValuePtr("misc:close_special_on_empty")->intValue; + + const int OLDWORKSPACE = m_iWorkspaceID; + m_iWorkspaceID = workspaceID; const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID); @@ -353,6 +357,15 @@ void CWindow::moveToWorkspace(int workspaceID) { // update xwayland coords g_pXWaylandManager->setWindowSize(this, m_vRealSize.vec()); + + if (g_pCompositor->isWorkspaceSpecial(OLDWORKSPACE) && g_pCompositor->getWindowsOnWorkspace(OLDWORKSPACE) == 0 && *PCLOSEONLASTSPECIAL) { + const auto PWS = g_pCompositor->getWorkspaceByID(OLDWORKSPACE); + + if (PWS) { + if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWS->m_iMonitorID); PMONITOR) + PMONITOR->setSpecialWorkspace(nullptr); + } + } } CWindow* CWindow::X11TransientFor() { From 14a3c939ce019623126893aa4c454e62bb29779c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 24 Oct 2023 01:03:40 +0100 Subject: [PATCH 116/513] hyprctl: log monitor id in workspaces request fixes #3640 --- src/debug/HyprCtl.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 309954a7..914a02e0 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -215,17 +215,19 @@ static std::string getWorkspaceData(CWorkspace* w, HyprCtl::eHyprCtlOutputFormat "id": {}, "name": "{}", "monitor": "{}", + "monitorID": {}, "windows": {}, "hasfullscreen": {}, "lastwindow": "0x{:x}", "lastwindowtitle": "{}" }})#", - w->m_iID, escapeJSONStrings(w->m_szName), escapeJSONStrings(PMONITOR ? PMONITOR->szName : "?"), g_pCompositor->getWindowsOnWorkspace(w->m_iID), + w->m_iID, escapeJSONStrings(w->m_szName), escapeJSONStrings(PMONITOR ? PMONITOR->szName : "?"), + escapeJSONStrings(PMONITOR ? std::to_string(PMONITOR->ID) : "undefined"), g_pCompositor->getWindowsOnWorkspace(w->m_iID), ((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false"), (uintptr_t)PLASTW, PLASTW ? escapeJSONStrings(PLASTW->m_szTitle) : ""); } else { - return std::format("workspace ID {} ({}) on monitor {}:\n\twindows: {}\n\thasfullscreen: {}\n\tlastwindow: 0x{:x}\n\tlastwindowtitle: {}\n\n", w->m_iID, w->m_szName, - PMONITOR ? PMONITOR->szName : "?", g_pCompositor->getWindowsOnWorkspace(w->m_iID), (int)w->m_bHasFullscreenWindow, (uintptr_t)PLASTW, - PLASTW ? PLASTW->m_szTitle : ""); + return std::format("workspace ID {} ({}) on monitor {}:\n\tmonitorID: {}\n\twindows: {}\n\thasfullscreen: {}\n\tlastwindow: 0x{:x}\n\tlastwindowtitle: {}\n\n", w->m_iID, + w->m_szName, PMONITOR ? PMONITOR->szName : "?", PMONITOR ? std::to_string(PMONITOR->ID) : "null", g_pCompositor->getWindowsOnWorkspace(w->m_iID), + (int)w->m_bHasFullscreenWindow, (uintptr_t)PLASTW, PLASTW ? PLASTW->m_szTitle : ""); } } @@ -246,7 +248,7 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, HyprCtl::eHyprC std::string result = std::format(R"#({{ "workspaceString": "{}"{}{}{}{}{}{}{}{} }})#", - escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, borderSize, border, rounding, decorate, shadow); + escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, borderSize, border, rounding, decorate, shadow); return result; } else { @@ -262,7 +264,7 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, HyprCtl::eHyprC const std::string shadow = std::format("\tshadow: {}\n", (bool)(r.shadow) ? boolToString(r.shadow.value()) : ""); std::string result = std::format("Workspace rule {}:\n{}{}{}{}{}{}{}{}{}{}\n", escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, - borderSize, border, rounding, decorate, shadow); + borderSize, border, rounding, decorate, shadow); return result; } From 50a80efad5f9293a2c113545848dd32a61797e23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= Date: Tue, 24 Oct 2023 18:19:45 +0100 Subject: [PATCH 117/513] flake.lock: update nixpkgs and xdph --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 329aaec8..e3ef7da8 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1694767346, - "narHash": "sha256-5uH27SiVFUwsTsqC5rs3kS7pBoNhtoy9QfTP9BmknGk=", + "lastModified": 1697723726, + "narHash": "sha256-SaTWPkI8a5xSHX/rrKzUe+/uVNy6zCGMXgoeMb7T9rg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "ace5093e36ab1e95cb9463863491bee90d5a4183", + "rev": "7c9cc5a6e5d38010801741ac830a3f8fd667a7a0", "type": "github" }, "original": { @@ -95,11 +95,11 @@ ] }, "locked": { - "lastModified": 1694628480, - "narHash": "sha256-Qg9hstRw0pvjGu5hStkr2UX1D73RYcQ9Ns/KnZMIm9w=", + "lastModified": 1697981233, + "narHash": "sha256-y8q4XUwx+gVK7i2eLjfR32lVo7TYvEslyzrmzYEaPZU=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "8f45a6435069b9e24ebd3160eda736d7a391cbf2", + "rev": "22e7a65ff9633e1dedfa5317fdffc49f68de2ff2", "type": "github" }, "original": { From 03771d3aa9d4c0036baf830c3fa385740d43cd60 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 24 Oct 2023 21:28:55 +0100 Subject: [PATCH 118/513] windowrules: add nearestneighbor --- src/Window.cpp | 3 +++ src/Window.hpp | 1 + src/config/ConfigManager.cpp | 2 +- src/debug/HyprCtl.cpp | 2 ++ src/render/Renderer.cpp | 8 +++++++- 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Window.cpp b/src/Window.cpp index ca9625ad..7825e7d3 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -516,6 +516,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { m_sAdditionalConfigData.forceOpaque = true; } else if (r.szRule == "immediate") { m_sAdditionalConfigData.forceTearing = true; + } else if (r.szRule == "nearestneighbor") { + m_sAdditionalConfigData.nearestNeighbor = true; } else if (r.szRule.starts_with("rounding")) { try { m_sAdditionalConfigData.rounding = std::stoi(r.szRule.substr(r.szRule.find_first_of(' ') + 1)); @@ -605,6 +607,7 @@ void CWindow::updateDynamicRules() { m_sAdditionalConfigData.keepAspectRatio = false; m_sAdditionalConfigData.xray = -1; m_sAdditionalConfigData.forceTearing = false; + m_sAdditionalConfigData.nearestNeighbor = false; const auto WINDOWRULES = g_pConfigManager->getMatchingRules(this); for (auto& r : WINDOWRULES) { diff --git a/src/Window.hpp b/src/Window.hpp index b54ecdbc..dfec0ab5 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -143,6 +143,7 @@ struct SWindowAdditionalConfigData { CWindowOverridableVar xray = -1; // -1 means unset, takes precedence over the renderdata one CWindowOverridableVar borderSize = -1; // -1 means unset, takes precedence over the renderdata one CWindowOverridableVar forceTearing = false; + CWindowOverridableVar nearestNeighbor = false; }; struct SWindowRule { diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 2ecac5c9..0d9cc288 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -935,7 +935,7 @@ bool windowRuleValid(const std::string& RULE) { RULE == "nomaximizerequest" || RULE == "fakefullscreen" || RULE == "nomaxsize" || RULE == "pin" || RULE == "noanim" || RULE == "dimaround" || RULE == "windowdance" || RULE == "maximize" || RULE == "keepaspectratio" || RULE.starts_with("animation") || RULE.starts_with("rounding") || RULE.starts_with("workspace") || RULE.starts_with("bordercolor") || RULE == "forcergbx" || RULE == "noinitialfocus" || RULE == "stayfocused" || RULE.starts_with("bordersize") || RULE.starts_with("xray") || - RULE.starts_with("center") || RULE.starts_with("group") || RULE == "immediate"; + RULE.starts_with("center") || RULE.starts_with("group") || RULE == "immediate" || RULE == "nearestneighbor"; } bool layerRuleValid(const std::string& RULE) { diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 914a02e0..378880b1 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1073,6 +1073,8 @@ std::string dispatchSetProp(std::string request) { PWINDOW->m_sAdditionalConfigData.keepAspectRatio.forceSetIgnoreLocked(configStringToInt(VAL), lock); } else if (PROP == "immediate") { PWINDOW->m_sAdditionalConfigData.forceTearing.forceSetIgnoreLocked(configStringToInt(VAL), lock); + } else if (PROP == "nearestneighbor") { + PWINDOW->m_sAdditionalConfigData.nearestNeighbor.forceSetIgnoreLocked(configStringToInt(VAL), lock); } else { return "prop not found"; } diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index e0966302..4326b89f 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -427,7 +427,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, Vector2D{renderdata.x, renderdata.y} - PREOFFSETPOS); static auto* const PXWLUSENN = &g_pConfigManager->getConfigValuePtr("xwayland:use_nearest_neighbor")->intValue; - if (pWindow->m_bIsX11 && *PXWLUSENN) + if ((pWindow->m_bIsX11 && *PXWLUSENN) || pWindow->m_sAdditionalConfigData.nearestNeighbor.toUnderlying()) g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; wlr_surface_for_each_surface(pWindow->m_pWLSurface.wlr(), renderSurface, &renderdata); @@ -483,7 +483,13 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* renderdata.dontRound = true; // don't round popups renderdata.pMonitor = pMonitor; renderdata.squishOversized = false; // don't squish popups + + if (pWindow->m_sAdditionalConfigData.nearestNeighbor.toUnderlying()) + g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; + wlr_xdg_surface_for_each_popup_surface(pWindow->m_uSurface.xdg, renderSurface, &renderdata); + + g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false; } } From df00727310b8a428a4977878cdf5597373a2ad31 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 25 Oct 2023 00:27:16 +0100 Subject: [PATCH 119/513] deps: update wlroots --- src/Compositor.cpp | 3 --- src/Compositor.hpp | 1 - src/events/Monitors.cpp | 2 +- src/includes.hpp | 1 - src/protocols/Screencopy.cpp | 4 ++-- src/protocols/ToplevelExport.cpp | 2 +- subprojects/wlroots | 2 +- 7 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 1163acca..e5242054 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -215,7 +215,6 @@ void CCompositor::initServer() { m_sWLRPresentation = wlr_presentation_create(m_sWLDisplay, m_sWLRBackend); - m_sWLRIdle = wlr_idle_create(m_sWLDisplay); m_sWLRIdleNotifier = wlr_idle_notifier_v1_create(m_sWLDisplay); m_sWLRLayerShell = wlr_layer_shell_v1_create(m_sWLDisplay, 4); @@ -2580,12 +2579,10 @@ CWindow* CCompositor::getForceFocus() { } void CCompositor::notifyIdleActivity() { - wlr_idle_notify_activity(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat); wlr_idle_notifier_v1_notify_activity(g_pCompositor->m_sWLRIdleNotifier, g_pCompositor->m_sSeat.seat); } void CCompositor::setIdleActivityInhibit(bool enabled) { - wlr_idle_set_enabled(g_pCompositor->m_sWLRIdle, g_pCompositor->m_sSeat.seat, enabled); wlr_idle_notifier_v1_set_inhibited(g_pCompositor->m_sWLRIdleNotifier, !enabled); } void CCompositor::arrangeMonitors() { diff --git a/src/Compositor.hpp b/src/Compositor.hpp index fdbac136..ae536c91 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -54,7 +54,6 @@ class CCompositor { wlr_drm_lease_v1_manager* m_sWRLDRMLeaseMgr; wlr_xdg_activation_v1* m_sWLRXDGActivation; wlr_output_layout* m_sWLROutputLayout; - wlr_idle* m_sWLRIdle; wlr_idle_notifier_v1* m_sWLRIdleNotifier; wlr_layer_shell_v1* m_sWLRLayerShell; wlr_xdg_shell* m_sWLRXDGShell; diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 8619ade3..fa36c53c 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -251,7 +251,7 @@ void Events::listener_monitorCommit(void* owner, void* data) { const auto E = (wlr_output_event_commit*)data; - if (E->committed & WLR_OUTPUT_STATE_BUFFER) { + if (E->state->committed & WLR_OUTPUT_STATE_BUFFER) { g_pProtocolManager->m_pScreencopyProtocolManager->onOutputCommit(PMONITOR, E); g_pProtocolManager->m_pToplevelExportProtocolManager->onOutputCommit(PMONITOR, E); } diff --git a/src/includes.hpp b/src/includes.hpp index 1205f55c..a70815dc 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -47,7 +47,6 @@ extern "C" { #include #include #include -#include #include #include #include diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index a84f853f..aaec0fab 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -263,7 +263,7 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou return; } - const auto PBUFFER = wlr_buffer_from_resource(buffer); + const auto PBUFFER = wlr_buffer_try_from_resource(buffer); if (!PBUFFER) { Debug::log(ERR, "[sc] invalid buffer in {:x}", (uintptr_t)PFRAME); wl_resource_post_error(PFRAME->resource, ZWLR_SCREENCOPY_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer"); @@ -332,7 +332,7 @@ void CScreencopyProtocolManager::copyFrame(wl_client* client, wl_resource* resou } void CScreencopyProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_output_event_commit* e) { - m_pLastMonitorBackBuffer = e->buffer; + m_pLastMonitorBackBuffer = e->state->buffer; shareAllFrames(pMonitor); m_pLastMonitorBackBuffer = nullptr; } diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 828ad35f..3515d652 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -229,7 +229,7 @@ void CToplevelExportProtocolManager::copyFrame(wl_client* client, wl_resource* r return; } - const auto PBUFFER = wlr_buffer_from_resource(buffer); + const auto PBUFFER = wlr_buffer_try_from_resource(buffer); if (!PBUFFER) { wl_resource_post_error(PFRAME->resource, HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_INVALID_BUFFER, "invalid buffer"); removeFrame(PFRAME); diff --git a/subprojects/wlroots b/subprojects/wlroots index 3406c1b1..47bf87ad 160000 --- a/subprojects/wlroots +++ b/subprojects/wlroots @@ -1 +1 @@ -Subproject commit 3406c1b17a4a7e6d4e2a7d9c1176affa72bce1bc +Subproject commit 47bf87ade2bd32395615a385ebde1fefbcdf79a2 From a1b138a6258b00787cea43bddc48b7caa8cca3a0 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 24 Oct 2023 23:28:24 +0000 Subject: [PATCH 120/513] [gha] Nix: update wlroots --- flake.lock | 8 ++++---- flake.nix | 2 +- subprojects/wlroots.wrap | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index e3ef7da8..55ebc8c6 100644 --- a/flake.lock +++ b/flake.lock @@ -67,18 +67,18 @@ "flake": false, "locked": { "host": "gitlab.freedesktop.org", - "lastModified": 1696410538, - "narHash": "sha256-ecDhdYLXWHsxMv+EWG36mCNDvzRbu9qfjH7dLxL7aGM=", + "lastModified": 1697909146, + "narHash": "sha256-jU0I6FoCKnj4zIBL4daosFWh81U1fM719Z6cae8PxSY=", "owner": "wlroots", "repo": "wlroots", - "rev": "3406c1b17a4a7e6d4e2a7d9c1176affa72bce1bc", + "rev": "47bf87ade2bd32395615a385ebde1fefbcdf79a2", "type": "gitlab" }, "original": { "host": "gitlab.freedesktop.org", "owner": "wlroots", "repo": "wlroots", - "rev": "3406c1b17a4a7e6d4e2a7d9c1176affa72bce1bc", + "rev": "47bf87ade2bd32395615a385ebde1fefbcdf79a2", "type": "gitlab" } }, diff --git a/flake.nix b/flake.nix index 4f0c1654..78677c20 100644 --- a/flake.nix +++ b/flake.nix @@ -12,7 +12,7 @@ host = "gitlab.freedesktop.org"; owner = "wlroots"; repo = "wlroots"; - rev = "3406c1b17a4a7e6d4e2a7d9c1176affa72bce1bc"; + rev = "47bf87ade2bd32395615a385ebde1fefbcdf79a2"; flake = false; }; diff --git a/subprojects/wlroots.wrap b/subprojects/wlroots.wrap index 98f93a53..b3cac63f 100644 --- a/subprojects/wlroots.wrap +++ b/subprojects/wlroots.wrap @@ -1,7 +1,7 @@ [wrap-git] directory = wlroots url = https://gitlab.freedesktop.org/wlroots/wlroots.git -revision = 3406c1b17a4a7e6d4e2a7d9c1176affa72bce1bc +revision = 47bf87ade2bd32395615a385ebde1fefbcdf79a2 depth = 1 diff_files = wlroots-meson-build.patch From 6650e4ba85568a687b1de79eb7375cabfa68e848 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 25 Oct 2023 18:31:52 +0100 Subject: [PATCH 121/513] compositor: remove old comment --- src/Compositor.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index e5242054..073f40f1 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -121,7 +121,6 @@ void CCompositor::initServer() { signal(SIGSEGV, handleUnrecoverableSignal); signal(SIGABRT, handleUnrecoverableSignal); signal(SIGUSR1, handleUserSignal); - //wl_event_loop_add_signal(m_sWLEventLoop, SIGINT, handleCritSignal, nullptr); initManagers(STAGE_PRIORITY); From 8991be671fb231ebe268352fe9cc883911b066c2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 25 Oct 2023 22:05:04 +0100 Subject: [PATCH 122/513] renderer: respect viewporter dest on base surfaces --- src/helpers/WLSurface.cpp | 13 +++++++++++-- src/helpers/WLSurface.hpp | 1 + src/render/Renderer.cpp | 9 +++++---- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/helpers/WLSurface.cpp b/src/helpers/WLSurface.cpp index a34c77a1..3d3800cb 100644 --- a/src/helpers/WLSurface.cpp +++ b/src/helpers/WLSurface.cpp @@ -38,11 +38,20 @@ Vector2D CWLSurface::correctSmallVec() const { if (!m_pOwner || !exists() || !small() || m_bFillIgnoreSmall) return {}; - return Vector2D{(m_pOwner->m_vReportedSize.x - m_pWLRSurface->current.buffer_width) / 2, (m_pOwner->m_vReportedSize.y - m_pWLRSurface->current.buffer_height) / 2}.clamp( - {}, {INFINITY, INFINITY}) * + 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}; +} + void CWLSurface::destroy() { if (!m_pWLRSurface) return; diff --git a/src/helpers/WLSurface.hpp b/src/helpers/WLSurface.hpp index ee6574de..8b4ef835 100644 --- a/src/helpers/WLSurface.hpp +++ b/src/helpers/WLSurface.hpp @@ -22,6 +22,7 @@ class CWLSurface { 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; // allow stretching. Useful for plugins. bool m_bFillIgnoreSmall = false; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 4326b89f..f5a79bdf 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -31,17 +31,18 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { if (PSURFACE && !PSURFACE->m_bFillIgnoreSmall && PSURFACE->small() /* guarantees m_pOwner */) { const auto CORRECT = PSURFACE->correctSmallVec(); + const auto SIZE = PSURFACE->getViewporterCorrectedSize(); const auto INTERACTIVERESIZEINPROGRESS = g_pInputManager->currentlyDraggedWindow == PSURFACE->m_pOwner && g_pInputManager->dragMode == MBIND_RESIZE; if (!INTERACTIVERESIZEINPROGRESS) { windowBox.x += CORRECT.x; windowBox.y += CORRECT.y; - windowBox.width = (double)surface->current.buffer_width * (PSURFACE->m_pOwner->m_vRealSize.vec().x / PSURFACE->m_pOwner->m_vReportedSize.x); - windowBox.height = (double)surface->current.buffer_height * (PSURFACE->m_pOwner->m_vRealSize.vec().y / PSURFACE->m_pOwner->m_vReportedSize.y); + windowBox.width = SIZE.x * (PSURFACE->m_pOwner->m_vRealSize.vec().x / PSURFACE->m_pOwner->m_vReportedSize.x); + windowBox.height = SIZE.y * (PSURFACE->m_pOwner->m_vRealSize.vec().y / PSURFACE->m_pOwner->m_vReportedSize.y); } else { - windowBox.width = (double)surface->current.buffer_width; - windowBox.height = (double)surface->current.buffer_height; + windowBox.width = SIZE.x; + windowBox.height = SIZE.y; } } From 5b0dc779ed91b08a9b0bfafb97b28f927dfdda0c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 25 Oct 2023 22:20:58 +0100 Subject: [PATCH 123/513] renderer: blur properly behind small surfaces --- src/render/Renderer.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index f5a79bdf..290e5171 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -431,6 +431,12 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* if ((pWindow->m_bIsX11 && *PXWLUSENN) || pWindow->m_sAdditionalConfigData.nearestNeighbor.toUnderlying()) g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; + if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall && renderdata.blur) { + wlr_box wb = {renderdata.x, renderdata.y, renderdata.w, renderdata.h}; + g_pHyprOpenGL->renderRectWithBlur(&wb, CColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1); + renderdata.blur = false; + } + wlr_surface_for_each_surface(pWindow->m_pWLSurface.wlr(), renderSurface, &renderdata); g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false; From b0b88a63b6d17b759a85c28cab29c5986fa6e3ff Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 25 Oct 2023 22:38:14 +0100 Subject: [PATCH 124/513] renderer: fix missed box scale --- src/render/Renderer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 290e5171..1e95c865 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -433,6 +433,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall && renderdata.blur) { wlr_box wb = {renderdata.x, renderdata.y, renderdata.w, renderdata.h}; + scaleBox(&wb, pMonitor->scale); g_pHyprOpenGL->renderRectWithBlur(&wb, CColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1); renderdata.blur = false; } From 5cc33b4e8c3e672202d5167652a4e49ff1acf105 Mon Sep 17 00:00:00 2001 From: fufexan Date: Thu, 26 Oct 2023 00:03:23 +0000 Subject: [PATCH 125/513] [gha] Nix: update inputs --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 55ebc8c6..8bb0d13d 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1697723726, - "narHash": "sha256-SaTWPkI8a5xSHX/rrKzUe+/uVNy6zCGMXgoeMb7T9rg=", + "lastModified": 1698134075, + "narHash": "sha256-foCD+nuKzfh49bIoiCBur4+Fx1nozo+4C/6k8BYk4sg=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "7c9cc5a6e5d38010801741ac830a3f8fd667a7a0", + "rev": "8efd5d1e283604f75a808a20e6cde0ef313d07d4", "type": "github" }, "original": { From 07714dd5bd9ff60e10170e11b535409e1bbc92ef Mon Sep 17 00:00:00 2001 From: Tyler Schneider Date: Wed, 25 Oct 2023 19:05:10 -0600 Subject: [PATCH 126/513] input: Apply scaling to cursorPosOnActivate position (#3664) --- src/managers/input/InputManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 5231a9a7..95240d1a 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1202,7 +1202,7 @@ void CInputManager::constrainMouse(SMouse* pMouse, wlr_pointer_constraint_v1* co g_pXWaylandManager->xwaylandToWaylandCoords({PWINDOW->m_uSurface.xwayland->x, PWINDOW->m_uSurface.xwayland->y})) : PWINDOW->m_vRealPosition.goalv(); - PCONSTRAINT->cursorPosOnActivate = MOUSECOORDS - RELATIVETO; + PCONSTRAINT->cursorPosOnActivate = (MOUSECOORDS - RELATIVETO) * PWINDOW->m_fX11SurfaceScaledBy; } if (constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) { From 92cf1c23371e35fa352da13305d8489a9e08d540 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 26 Oct 2023 18:54:07 +0100 Subject: [PATCH 127/513] input: fix mouse down handling on unset last surface fixes #3659 --- src/managers/input/InputManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 95240d1a..d2cb27b8 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -182,7 +182,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { // update stuff updateDragIcon(); - if (!m_sDrag.drag && !m_lCurrentlyHeldButtons.empty() && g_pCompositor->m_pLastFocus) { + if (!m_sDrag.drag && !m_lCurrentlyHeldButtons.empty() && g_pCompositor->m_pLastFocus && m_pLastMouseSurface) { if (m_bLastFocusOnLS) { foundSurface = m_pLastMouseSurface; pFoundLayerSurface = g_pCompositor->getLayerSurfaceFromSurface(foundSurface); @@ -310,6 +310,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { } wlr_seat_pointer_clear_focus(g_pCompositor->m_sSeat.seat); + m_pLastMouseSurface = nullptr; if (refocus || !g_pCompositor->m_pLastWindow) // if we are forcing a refocus, and we don't find a surface, clear the kb focus too! g_pCompositor->focusWindow(nullptr); From 732b0584890bae87ab079aaa95b5b2b822b99d49 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 26 Oct 2023 22:17:49 +0100 Subject: [PATCH 128/513] input: send motion events on focusWindow if follows_mouse is 0 --- src/Compositor.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 073f40f1..9b36b338 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -883,6 +883,8 @@ CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) { void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) { + static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; + if (g_pCompositor->m_sSeat.exclusiveClient) { Debug::log(LOG, "Disallowing setting focus to a window due to there being an active input inhibitor layer."); return; @@ -1006,6 +1008,9 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) { } else { std::rotate(m_vWindowFocusHistory.begin(), HISTORYPIVOT, HISTORYPIVOT + 1); } + + if (*PFOLLOWMOUSE == 0) + g_pInputManager->sendMotionEventsToFocused(); } void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) { From 47256a6ed8fb486fd351834c85235a0672d69abc Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 26 Oct 2023 22:21:13 +0100 Subject: [PATCH 129/513] input: remove incorrect check in re-enter fixes #3659 --- src/managers/input/InputManager.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index d2cb27b8..1e8760aa 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -379,11 +379,8 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { } if (pFoundWindow == g_pCompositor->m_pLastWindow) { - if (foundSurface != g_pCompositor->m_pLastFocus || m_bLastFocusOnLS) { - // ^^^ changed the subsurface ^^^ came back from a LS - m_pLastMouseSurface = foundSurface; - wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y); - } + m_pLastMouseSurface = foundSurface; + wlr_seat_pointer_notify_enter(g_pCompositor->m_sSeat.seat, foundSurface, surfaceLocal.x, surfaceLocal.y); } if (FOLLOWMOUSE != 0 || pFoundWindow == g_pCompositor->m_pLastWindow) From 1d47e2c4088b74961fdc59aba558d84f4751fed1 Mon Sep 17 00:00:00 2001 From: Antoine Dutot Date: Fri, 27 Oct 2023 11:15:29 +0200 Subject: [PATCH 130/513] input: fix force_zero_scaling for tablet and touch (#3644) * Attempt to fix force_zero_scaling for tablet and touch for XWayland apps. * Formated using clang-format. * Simpler way to compute touch origin. --- src/managers/input/Tablets.cpp | 12 ++++++++---- src/managers/input/Touch.cpp | 10 ++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index 77dd737c..e5968a5a 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -244,8 +244,6 @@ void CInputManager::focusTablet(STablet* pTab, wlr_tablet_tool* pTool, bool moti if (const auto PWINDOW = g_pCompositor->m_pLastWindow; PWINDOW) { const auto CURSORPOS = g_pInputManager->getMouseCoordsInternal(); - const auto LOCAL = CURSORPOS - PWINDOW->m_vRealPosition.goalv(); - if (PTOOL->pSurface != g_pCompositor->m_pLastFocus) wlr_tablet_v2_tablet_tool_notify_proximity_out(PTOOL->wlrTabletToolV2); @@ -254,8 +252,14 @@ void CInputManager::focusTablet(STablet* pTab, wlr_tablet_tool* pTool, bool moti wlr_tablet_v2_tablet_tool_notify_proximity_in(PTOOL->wlrTabletToolV2, pTab->wlrTabletV2, g_pCompositor->m_pLastFocus); } - if (motion) - wlr_tablet_v2_tablet_tool_notify_motion(PTOOL->wlrTabletToolV2, LOCAL.x, LOCAL.y); + if (motion) { + auto local = CURSORPOS - PWINDOW->m_vRealPosition.goalv(); + + if (PWINDOW->m_bIsX11) + local = local * PWINDOW->m_fX11SurfaceScaledBy; + + wlr_tablet_v2_tablet_tool_notify_motion(PTOOL->wlrTabletToolV2, local.x, local.y); + } } else { if (PTOOL->pSurface) wlr_tablet_v2_tablet_tool_notify_proximity_out(PTOOL->wlrTabletToolV2); diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 19e29c1b..24e299a7 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -32,12 +32,12 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) { if (m_sTouchData.touchFocusWindow) { if (m_sTouchData.touchFocusWindow->m_bIsX11) { - local = g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchFocusWindow->m_vRealPosition.goalv(); + local = (g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchFocusWindow->m_vRealPosition.goalv()) * m_sTouchData.touchFocusWindow->m_fX11SurfaceScaledBy; + m_sTouchData.touchSurfaceOrigin = m_sTouchData.touchFocusWindow->m_vRealPosition.goalv(); } else { g_pCompositor->vectorWindowToSurface(g_pInputManager->getMouseCoordsInternal(), m_sTouchData.touchFocusWindow, local); + m_sTouchData.touchSurfaceOrigin = g_pInputManager->getMouseCoordsInternal() - local; } - - m_sTouchData.touchSurfaceOrigin = g_pInputManager->getMouseCoordsInternal() - local; } else if (m_sTouchData.touchFocusLS) { local = g_pInputManager->getMouseCoordsInternal() - Vector2D(m_sTouchData.touchFocusLS->geometry.x, m_sTouchData.touchFocusLS->geometry.y); @@ -63,7 +63,9 @@ void CInputManager::onTouchMove(wlr_touch_motion_event* e) { wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, PMONITOR->vecPosition.x + e->x * PMONITOR->vecSize.x, PMONITOR->vecPosition.y + e->y * PMONITOR->vecSize.y); - const auto local = g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchSurfaceOrigin; + auto local = g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchSurfaceOrigin; + if (m_sTouchData.touchFocusWindow->m_bIsX11) + local = local * m_sTouchData.touchFocusWindow->m_fX11SurfaceScaledBy; wlr_seat_touch_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id, local.x, local.y); wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, local.x, local.y); From 4a4e13f8acedd2dc44236deed13fd47096cbe508 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 27 Oct 2023 12:45:14 +0100 Subject: [PATCH 131/513] events: ignore takes_over_fullscreen for floating windows fixes #3622. Floating windows should not respect the config option, they should be shown on top. That option is meant for tiled only --- src/events/Windows.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 89b327b0..c0910abe 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -468,7 +468,7 @@ void Events::listener_mapWindow(void* owner, void* data) { const auto PLSFROMFOCUS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus); if (PLSFROMFOCUS && PLSFROMFOCUS->layerSurface->current.keyboard_interactive) PWINDOW->m_bNoInitialFocus = true; - if (PWORKSPACE->m_bHasFullscreenWindow && !requestsFullscreen) { + if (PWORKSPACE->m_bHasFullscreenWindow && !requestsFullscreen && !PWINDOW->m_bIsFloating) { if (*PNEWTAKESOVERFS == 0) PWINDOW->m_bNoInitialFocus = true; else if (*PNEWTAKESOVERFS == 2) From 7f4b0aaadc8348e8814285d7ec582cf737b62d3b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 28 Oct 2023 17:22:31 +0100 Subject: [PATCH 132/513] hyprctl: add focusHistoryID to hyprctl clients fixes #3661 --- src/debug/HyprCtl.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 378880b1..e7191ae1 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -132,6 +132,14 @@ static std::string getGroupedData(CWindow* w, HyprCtl::eHyprCtlOutputFormat form } static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat format) { + auto getFocusHistoryID = [](CWindow* wnd) -> int { + for (size_t i = 0; i < g_pCompositor->m_vWindowFocusHistory.size(); ++i) { + if (g_pCompositor->m_vWindowFocusHistory[i] == wnd) + return i; + } + return -1; + }; + if (format == HyprCtl::FORMAT_JSON) { return std::format( R"#({{ @@ -157,7 +165,8 @@ static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat forma "fullscreenMode": {}, "fakeFullscreen": {}, "grouped": [{}], - "swallowing": "0x{:x}" + "swallowing": "0x{:x}", + "focusHistoryID": {} }},)#", (uintptr_t)w, (w->m_bIsMapped ? "true" : "false"), (w->isHidden() ? "true" : "false"), (int)w->m_vRealPosition.goalv().x, (int)w->m_vRealPosition.goalv().y, (int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y, w->m_iWorkspaceID, @@ -168,13 +177,13 @@ static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat forma escapeJSONStrings(g_pXWaylandManager->getTitle(w)), escapeJSONStrings(w->m_szInitialClass), escapeJSONStrings(w->m_szInitialTitle), w->getPID(), ((int)w->m_bIsX11 == 1 ? "true" : "false"), (w->m_bPinned ? "true" : "false"), (w->m_bIsFullscreen ? "true" : "false"), (w->m_bIsFullscreen ? (g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? (int)g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_efFullscreenMode : 0) : 0), - w->m_bFakeFullscreenState ? "true" : "false", getGroupedData(w, format), (uintptr_t)w->m_pSwallowed); + w->m_bFakeFullscreenState ? "true" : "false", getGroupedData(w, format), (uintptr_t)w->m_pSwallowed, getFocusHistoryID(w)); } else { return std::format( "Window {:x} -> {}:\n\tmapped: {}\n\thidden: {}\n\tat: {},{}\n\tsize: {},{}\n\tworkspace: {} ({})\n\tfloating: {}\n\tmonitor: {}\n\tclass: {}\n\ttitle: " "{}\n\tinitialClass: {}\n\tinitialTitle: {}\n\tpid: " "{}\n\txwayland: {}\n\tpinned: " - "{}\n\tfullscreen: {}\n\tfullscreenmode: {}\n\tfakefullscreen: {}\n\tgrouped: {}\n\tswallowing: {:x}\n\n", + "{}\n\tfullscreen: {}\n\tfullscreenmode: {}\n\tfakefullscreen: {}\n\tgrouped: {}\n\tswallowing: {:x}\n\tfocusHistoryID: {}\n\n", (uintptr_t)w, w->m_szTitle, (int)w->m_bIsMapped, (int)w->isHidden(), (int)w->m_vRealPosition.goalv().x, (int)w->m_vRealPosition.goalv().y, (int)w->m_vRealSize.goalv().x, (int)w->m_vRealSize.goalv().y, w->m_iWorkspaceID, (w->m_iWorkspaceID == -1 ? "" : @@ -183,7 +192,7 @@ static std::string getWindowData(CWindow* w, HyprCtl::eHyprCtlOutputFormat forma (int)w->m_bIsFloating, (int64_t)w->m_iMonitorID, g_pXWaylandManager->getAppIDClass(w), g_pXWaylandManager->getTitle(w), w->m_szInitialClass, w->m_szInitialTitle, w->getPID(), (int)w->m_bIsX11, (int)w->m_bPinned, (int)w->m_bIsFullscreen, (w->m_bIsFullscreen ? (g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_efFullscreenMode : 0) : 0), - (int)w->m_bFakeFullscreenState, getGroupedData(w, format), (uintptr_t)w->m_pSwallowed); + (int)w->m_bFakeFullscreenState, getGroupedData(w, format), (uintptr_t)w->m_pSwallowed, getFocusHistoryID(w)); } } From af9440152e19cee74b675e53087e032b9ccb5459 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 29 Oct 2023 16:59:50 +0000 Subject: [PATCH 133/513] pluginapi: add a config keyword adding method --- src/config/ConfigManager.cpp | 18 ++++++++++++++++-- src/config/ConfigManager.hpp | 11 ++++++++++- src/plugins/PluginAPI.cpp | 13 +++++++++++++ src/plugins/PluginAPI.hpp | 8 ++++++++ 4 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 0d9cc288..3d4d265a 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1389,8 +1389,15 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std:: else if (COMMAND.starts_with("plugin")) handlePlugin(COMMAND, VALUE); else { - configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE); - needsLayoutRecalc = 2; + // try config + const auto IT = std::find_if(pluginKeywords.begin(), pluginKeywords.end(), [&](const auto& other) { return other.name == COMMAND; }); + + if (IT != pluginKeywords.end()) { + IT->fn(COMMAND, VALUE); + } else { + configSetValueSafe(currentCategory + (currentCategory == "" ? "" : ":") + COMMAND, VALUE); + needsLayoutRecalc = 2; + } } if (dynamic) { @@ -1524,6 +1531,8 @@ void CConfigManager::parseLine(std::string& line) { } void CConfigManager::loadConfigLoadVars() { + EMIT_HOOK_EVENT("preConfigReload", nullptr); + Debug::log(LOG, "Reloading the config!"); parseError = ""; // reset the error currentCategory = ""; // reset the category @@ -2312,8 +2321,13 @@ void CConfigManager::addPluginConfigVar(HANDLE handle, const std::string& name, } } +void CConfigManager::addPluginKeyword(HANDLE handle, const std::string& name, std::function fn) { + pluginKeywords.emplace_back(SPluginKeyword{handle, name, fn}); +} + void CConfigManager::removePluginConfig(HANDLE handle) { std::erase_if(pluginConfigs, [&](const auto& other) { return other.first == handle; }); + std::erase_if(pluginKeywords, [&](const auto& other) { return other.handle == handle; }); } std::string CConfigManager::getDefaultWorkspaceFor(const std::string& name) { diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index c6c726bf..f89ae72c 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "../Window.hpp" #include "../helpers/WLClasses.hpp" @@ -71,6 +72,12 @@ struct SAnimationPropertyConfig { SAnimationPropertyConfig* pParentAnimation = nullptr; }; +struct SPluginKeyword { + HANDLE handle = 0; + std::string name = ""; + std::function fn; +}; + struct SExecRequestedRule { std::string szRule = ""; uint64_t iPid = 0; @@ -120,7 +127,8 @@ class CConfigManager { std::unordered_map getAnimationConfig(); void addPluginConfigVar(HANDLE handle, const std::string& name, const SConfigValue& value); - void removePluginConfig(HANDLE handle); + void addPluginKeyword(HANDLE handle, const std::string& name, std::function fun); + void removePluginConfig(HANDLE handle); // no-op when done. void dispatchExecOnce(); @@ -163,6 +171,7 @@ class CConfigManager { std::vector m_vDeclaredPlugins; std::unordered_map>> pluginConfigs; // stores plugin configs + std::vector pluginKeywords; bool isFirstLaunch = true; // For exec-once diff --git a/src/plugins/PluginAPI.cpp b/src/plugins/PluginAPI.cpp index 8d2f6627..a873644e 100644 --- a/src/plugins/PluginAPI.cpp +++ b/src/plugins/PluginAPI.cpp @@ -160,6 +160,19 @@ APICALL bool HyprlandAPI::addConfigValue(HANDLE handle, const std::string& name, return true; } +APICALL bool HyprlandAPI::addConfigKeyword(HANDLE handle, const std::string& name, std::function fn) { + auto* const PLUGIN = g_pPluginSystem->getPluginByHandle(handle); + + if (!g_pPluginSystem->m_bAllowConfigVars) + return false; + + if (!PLUGIN) + return false; + + g_pConfigManager->addPluginKeyword(handle, name, fn); + return true; +} + APICALL SConfigValue* HyprlandAPI::getConfigValue(HANDLE handle, const std::string& name) { auto* const PLUGIN = g_pPluginSystem->getPluginByHandle(handle); diff --git a/src/plugins/PluginAPI.hpp b/src/plugins/PluginAPI.hpp index 36cdbe63..30c6b4c7 100644 --- a/src/plugins/PluginAPI.hpp +++ b/src/plugins/PluginAPI.hpp @@ -114,6 +114,14 @@ namespace HyprlandAPI { */ APICALL bool addConfigValue(HANDLE handle, const std::string& name, const SConfigValue& value); + /* + Add a config keyword. + This method may only be called in "pluginInit" + + returns: true on success, false on fail + */ + APICALL bool addConfigKeyword(HANDLE handle, const std::string& name, std::function fn); + /* Get a config value. From 7a5234a0cca2508b7a5ede1fc60dc3ae8b72a51c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 29 Oct 2023 18:09:05 +0000 Subject: [PATCH 134/513] input: better cursor image infrastructure Improves handling of cursor images/surfaces Fixes an issue with decos and cursors Fixes #3471 --- src/Window.cpp | 4 ++ src/Window.hpp | 1 + src/helpers/WLSurface.cpp | 2 + src/managers/input/InputManager.cpp | 78 +++++++++++++++++++++++------ src/managers/input/InputManager.hpp | 19 ++++--- src/render/Renderer.cpp | 12 +++++ src/render/Renderer.hpp | 5 ++ 7 files changed, 100 insertions(+), 21 deletions(-) diff --git a/src/Window.cpp b/src/Window.cpp index 7825e7d3..fb46740b 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -171,6 +171,10 @@ wlr_box CWindow::getWindowInputBox() { return finalBox; } +wlr_box CWindow::getWindowMainSurfaceBox() { + return {m_vRealPosition.vec().x, m_vRealPosition.vec().y, m_vRealSize.vec().x, m_vRealSize.vec().y}; +} + SWindowDecorationExtents CWindow::getFullWindowReservedArea() { SWindowDecorationExtents extents; diff --git a/src/Window.hpp b/src/Window.hpp index dfec0ab5..f856b2a9 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -339,6 +339,7 @@ class CWindow { wlr_box getFullWindowBoundingBox(); SWindowDecorationExtents getFullWindowExtents(); wlr_box getWindowInputBox(); + wlr_box getWindowMainSurfaceBox(); wlr_box getWindowIdealBoundingBoxIgnoreReserved(); void updateWindowDecos(); pid_t getPID(); diff --git a/src/helpers/WLSurface.cpp b/src/helpers/WLSurface.cpp index 3d3800cb..ffd764a1 100644 --- a/src/helpers/WLSurface.cpp +++ b/src/helpers/WLSurface.cpp @@ -64,6 +64,8 @@ void CWLSurface::destroy() { g_pCompositor->m_pLastFocus = nullptr; if (g_pInputManager->m_pLastMouseSurface == m_pWLRSurface) g_pInputManager->m_pLastMouseSurface = nullptr; + if (g_pHyprRenderer->m_sLastCursorData.surf == m_pWLRSurface) + g_pInputManager->setCursorImageOverride("left_ptr"); m_pWLRSurface = nullptr; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 1e8760aa..b19a929c 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -301,9 +301,9 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (g_pHyprRenderer->m_bHasARenderedCursor) { // TODO: maybe wrap? if (m_ecbClickBehavior == CLICKMODE_KILL) - g_pHyprRenderer->setCursorFromName("crosshair"); + setCursorImageOverride("crosshair"); else - g_pHyprRenderer->setCursorFromName("left_ptr"); + setCursorImageOverride("left_ptr"); } m_bEmptyFocusCursorSet = true; @@ -355,6 +355,14 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { return; } + if (pFoundWindow && foundSurface == pFoundWindow->m_pWLSurface.wlr() && !m_bCursorImageOverridden) { + const auto BOX = pFoundWindow->getWindowMainSurfaceBox(); + if (!VECINRECT(mouseCoords, BOX.x, BOX.y, BOX.x + BOX.width, BOX.y + BOX.height)) + setCursorImageOverride("left_ptr"); + else + restoreCursorIconToApp(); + } + if (pFoundWindow) { // change cursor icon if hovering over border if (*PRESIZEONBORDER && *PRESIZECURSORICON) { @@ -460,25 +468,65 @@ void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_even if (!cursorImageUnlocked() || !g_pHyprRenderer->m_bHasARenderedCursor) return; - // cursorSurfaceInfo.pSurface = e->surface; + if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) { + m_sCursorSurfaceInfo.wlSurface.unassign(); - // if (e->surface) { - // hyprListener_CursorSurfaceDestroy.removeCallback(); - // hyprListener_CursorSurfaceDestroy.initCallback( - // &e->surface->events.destroy, [&](void* owner, void* data) { cursorSurfaceInfo.pSurface = nullptr; }, this, "InputManager"); - // cursorSurfaceInfo.vHotspot = {e->hotspot_x, e->hotspot_y}; - // } + if (e->surface) { + m_sCursorSurfaceInfo.wlSurface.assign(e->surface); + m_sCursorSurfaceInfo.vHotspot = {e->hotspot_x, e->hotspot_y}; + m_sCursorSurfaceInfo.hidden = false; + } else { + m_sCursorSurfaceInfo.vHotspot = {}; + m_sCursorSurfaceInfo.hidden = true; + } - if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) + m_sCursorSurfaceInfo.name = ""; + + m_sCursorSurfaceInfo.inUse = true; g_pHyprRenderer->setCursorSurface(e->surface, e->hotspot_x, e->hotspot_y); + } } void CInputManager::processMouseRequest(wlr_cursor_shape_manager_v1_request_set_shape_event* e) { if (!g_pHyprRenderer->m_bHasARenderedCursor || !cursorImageUnlocked()) return; - if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) - g_pHyprRenderer->setCursorFromName(wlr_cursor_shape_v1_name(e->shape)); + if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) { + m_sCursorSurfaceInfo.wlSurface.unassign(); + m_sCursorSurfaceInfo.vHotspot = {}; + m_sCursorSurfaceInfo.name = wlr_cursor_shape_v1_name(e->shape); + m_sCursorSurfaceInfo.hidden = false; + + m_sCursorSurfaceInfo.inUse = true; + g_pHyprRenderer->setCursorFromName(m_sCursorSurfaceInfo.name); + } +} + +void CInputManager::restoreCursorIconToApp() { + if (m_sCursorSurfaceInfo.inUse) + return; + + if (m_sCursorSurfaceInfo.hidden) { + g_pHyprRenderer->setCursorSurface(nullptr, 0, 0); + return; + } + + if (m_sCursorSurfaceInfo.name.empty()) { + if (m_sCursorSurfaceInfo.wlSurface.exists()) + g_pHyprRenderer->setCursorSurface(m_sCursorSurfaceInfo.wlSurface.wlr(), m_sCursorSurfaceInfo.vHotspot.x, m_sCursorSurfaceInfo.vHotspot.y); + } else { + g_pHyprRenderer->setCursorFromName(m_sCursorSurfaceInfo.name); + } + + m_sCursorSurfaceInfo.inUse = true; +} + +void CInputManager::setCursorImageOverride(const std::string& name) { + if (m_bCursorImageOverridden) + return; + + m_sCursorSurfaceInfo.inUse = false; + g_pHyprRenderer->setCursorFromName(name); } bool CInputManager::cursorImageUnlocked() { @@ -1487,7 +1535,8 @@ void CInputManager::destroySwitch(SSwitchDevice* pDevice) { void CInputManager::setCursorImageUntilUnset(std::string name) { g_pHyprRenderer->setCursorFromName(name.c_str()); - m_bCursorImageOverridden = true; + m_bCursorImageOverridden = true; + m_sCursorSurfaceInfo.inUse = false; } void CInputManager::unsetCursorImage() { @@ -1495,8 +1544,7 @@ void CInputManager::unsetCursorImage() { return; m_bCursorImageOverridden = false; - if (!g_pHyprRenderer->m_bWindowRequestedCursorHide) - g_pHyprRenderer->setCursorFromName("left_ptr"); + restoreCursorIconToApp(); } std::string CInputManager::deviceNameToInternalString(std::string in) { diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 670bc4da..b4d365ee 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -229,15 +229,22 @@ class CInputManager { void setBorderCursorIcon(eBorderIconDirection); void setCursorIconOnBorder(CWindow* w); + // temporary. Obeys setUntilUnset. + void setCursorImageOverride(const std::string& name); + // cursor surface - // struct cursorSI { - // wlr_surface* pSurface = nullptr; - // Vector2D vHotspot; - // bool bUsed = false; - // } cursorSurfaceInfo; - // DYNLISTENER(CursorSurfaceDestroy); + struct cursorSI { + bool hidden = false; // null surface = hidden + CWLSurface wlSurface; + Vector2D vHotspot; + std::string name; // if not empty, means set by name. + bool inUse = false; + } m_sCursorSurfaceInfo; + + void restoreCursorIconToApp(); // no-op if restored friend class CKeybindManager; + friend class CWLSurface; }; inline std::unique_ptr g_pInputManager; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 1e95c865..ea662867 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1940,11 +1940,23 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR void CHyprRenderer::setCursorSurface(wlr_surface* surf, int hotspotX, int hotspotY) { m_bCursorHasSurface = surf; + if (surf == m_sLastCursorData.surf) + return; + + m_sLastCursorData.name = ""; + m_sLastCursorData.surf = surf; + wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, surf, hotspotX, hotspotY); } void CHyprRenderer::setCursorFromName(const std::string& name) { m_bCursorHasSurface = true; + if (name == m_sLastCursorData.name) + return; + + m_sLastCursorData.name = name; + m_sLastCursorData.surf = nullptr; + wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, name.c_str()); } diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index e056db5c..859d1d6a 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -83,6 +83,11 @@ class CHyprRenderer { CTimer m_tRenderTimer; + struct { + wlr_surface* surf = nullptr; + std::string name; + } m_sLastCursorData; + private: void arrangeLayerArray(CMonitor*, const std::vector>&, bool, wlr_box*); void renderWorkspaceWindowsFullscreen(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) From 9abfa9efc627df0765652f862887626af02b5ae1 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Sun, 29 Oct 2023 20:14:47 +0000 Subject: [PATCH 135/513] input: handle mouse on decorations (#3560) --- src/layout/DwindleLayout.cpp | 27 +++--- src/layout/IHyprLayout.cpp | 3 + src/layout/MasterLayout.cpp | 27 +++--- src/managers/KeybindManager.cpp | 25 +++-- src/managers/input/InputManager.cpp | 19 ++-- src/managers/input/InputManager.hpp | 10 +- .../decorations/CHyprGroupBarDecoration.cpp | 97 ++++++++++++++++--- .../decorations/CHyprGroupBarDecoration.hpp | 8 ++ .../decorations/IHyprWindowDecoration.cpp | 8 ++ .../decorations/IHyprWindowDecoration.hpp | 6 ++ 10 files changed, 165 insertions(+), 65 deletions(-) diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index b034557e..984db38d 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -312,6 +312,19 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire return; } + if (!m_vOverrideFocalPoint && g_pInputManager->m_bWasDraggingWindow) { + for (auto& wd : OPENINGON->pWindow->m_dWindowDecorations) { + if (!wd->allowsInput()) + continue; + + if (wd->getWindowDecorationRegion().containsPoint(MOUSECOORDS)) { + if (!wd->onEndWindowDragOnDeco(pWindow, MOUSECOORDS)) + return; + break; + } + } + } + // if it's a group, add the window if (OPENINGON->pWindow->m_sGroupData.pNextWindow // target is group && !g_pKeybindManager->m_bGroupsLocked // global group lock disengaged @@ -327,18 +340,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire m_lDwindleNodesData.remove(*PNODE); - const wlr_box box = OPENINGON->pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents(); - if (wlr_box_contains_point(&box, MOUSECOORDS.x, MOUSECOORDS.y)) { // TODO: Deny when not using mouse - const int SIZE = OPENINGON->pWindow->getGroupSize(); - const int INDEX = (int)((MOUSECOORDS.x - box.x) * 2 * SIZE / box.width + 1) / 2 - 1; - CWindow* pWindowInsertAfter = OPENINGON->pWindow->getGroupWindowByIndex(INDEX); - pWindowInsertAfter->insertWindowToGroup(pWindow); - if (INDEX == -1) - std::swap(pWindow->m_sGroupData.pNextWindow->m_sGroupData.head, pWindow->m_sGroupData.head); - } else { - static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue; - (*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow); - } + static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue; + (*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow); OPENINGON->pWindow->setGroupCurrent(pWindow); pWindow->applyGroupRules(); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 61bc2266..2bbda858 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -254,6 +254,7 @@ void IHyprLayout::onEndDragWindow() { g_pInputManager->unsetCursorImage(); g_pInputManager->currentlyDraggedWindow = nullptr; + g_pInputManager->m_bWasDraggingWindow = true; if (DRAGGINGWINDOW->m_bDraggingTiled) { DRAGGINGWINDOW->m_bIsFloating = false; @@ -265,6 +266,8 @@ void IHyprLayout::onEndDragWindow() { g_pHyprRenderer->damageWindow(DRAGGINGWINDOW); g_pCompositor->focusWindow(DRAGGINGWINDOW); + + g_pInputManager->m_bWasDraggingWindow = false; } void IHyprLayout::onMouseMove(const Vector2D& mousePos) { diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index ebbcc805..6ee88512 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -94,6 +94,19 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); + if (g_pInputManager->m_bWasDraggingWindow) { + for (auto& wd : OPENINGON->pWindow->m_dWindowDecorations) { + if (!wd->allowsInput()) + continue; + + if (wd->getWindowDecorationRegion().containsPoint(MOUSECOORDS)) { + if (!wd->onEndWindowDragOnDeco(pWindow, MOUSECOORDS)) + return; + break; + } + } + } + // if it's a group, add the window if (OPENINGON && OPENINGON != PNODE && OPENINGON->pWindow->m_sGroupData.pNextWindow // target is group && !g_pKeybindManager->m_bGroupsLocked // global group lock disengaged @@ -109,18 +122,8 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc m_lMasterNodesData.remove(*PNODE); - const wlr_box box = OPENINGON->pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents(); - if (wlr_box_contains_point(&box, MOUSECOORDS.x, MOUSECOORDS.y)) { // TODO: Deny when not using mouse - const int SIZE = OPENINGON->pWindow->getGroupSize(); - const int INDEX = (int)((MOUSECOORDS.x - box.x) * 2 * SIZE / box.width + 1) / 2 - 1; - CWindow* pWindowInsertAfter = OPENINGON->pWindow->getGroupWindowByIndex(INDEX); - pWindowInsertAfter->insertWindowToGroup(pWindow); - if (INDEX == -1) - std::swap(pWindow->m_sGroupData.pNextWindow->m_sGroupData.head, pWindow->m_sGroupData.head); - } else { - static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue; - (*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow); - } + static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue; + (*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow); OPENINGON->pWindow->setGroupCurrent(pWindow); pWindow->applyGroupRules(); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 72e7f24e..23adc165 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1839,25 +1839,22 @@ void CKeybindManager::mouse(std::string args) { const auto mouseCoords = g_pInputManager->getMouseCoordsInternal(); CWindow* pWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords); - if (pWindow && !pWindow->m_bIsFullscreen && !pWindow->hasPopupAt(mouseCoords) && pWindow->m_sGroupData.pNextWindow) { - const wlr_box box = pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents(); - if (wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y)) { - const int SIZE = pWindow->getGroupSize(); - pWindow = pWindow->getGroupWindowByIndex((mouseCoords.x - box.x) * SIZE / box.width); + if (pWindow && !pWindow->m_bIsFullscreen && !pWindow->hasPopupAt(mouseCoords)) { + for (auto& wd : pWindow->m_dWindowDecorations) { + if (!wd->allowsInput()) + continue; - // hack - g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow); - if (!pWindow->m_bIsFloating) { - const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_bGroupsLocked; - g_pKeybindManager->m_bGroupsLocked = true; - g_pLayoutManager->getCurrentLayout()->onWindowCreated(pWindow); - g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV; + if (wd->getWindowDecorationRegion().containsPoint(mouseCoords)) { + wd->onBeginWindowDragOnDeco(mouseCoords); + break; } } } - g_pInputManager->currentlyDraggedWindow = pWindow; - g_pInputManager->dragMode = MBIND_MOVE; + if (!g_pInputManager->currentlyDraggedWindow) + g_pInputManager->currentlyDraggedWindow = pWindow; + + g_pInputManager->dragMode = MBIND_MOVE; g_pLayoutManager->getCurrentLayout()->onBeginDragWindow(); } else { g_pKeybindManager->m_bIsMouseBindActive = false; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index b19a929c..40d25858 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -583,16 +583,15 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { const auto mouseCoords = g_pInputManager->getMouseCoordsInternal(); const auto w = g_pCompositor->vectorToWindowIdeal(mouseCoords); - if (w && !w->m_bIsFullscreen && !w->hasPopupAt(mouseCoords) && w->m_sGroupData.pNextWindow) { - const wlr_box box = w->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents(); - if (wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y)) { - if (e->state == WLR_BUTTON_PRESSED) { - const int SIZE = w->getGroupSize(); - CWindow* pWindow = w->getGroupWindowByIndex((mouseCoords.x - box.x) * SIZE / box.width); - if (w != pWindow) - w->setGroupCurrent(pWindow); + if (w && !w->m_bIsFullscreen && !w->hasPopupAt(mouseCoords)) { + for (auto& wd : w->m_dWindowDecorations) { + if (!wd->allowsInput()) + continue; + + if (wd->getWindowDecorationRegion().containsPoint(mouseCoords)) { + wd->onMouseButtonOnDeco(mouseCoords, e); + return; } - return; } } @@ -1625,7 +1624,7 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) { wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; eBorderIconDirection direction = BORDERICON_NONE; wlr_box boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE), - box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; + box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; if (!wlr_box_contains_point(&boxFullGrabInput, mouseCoords.x, mouseCoords.y) || (!m_lCurrentlyHeldButtons.empty() && !currentlyDraggedWindow)) { direction = BORDERICON_NONE; diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index b4d365ee..554f91db 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -7,14 +7,12 @@ #include "../../helpers/Timer.hpp" #include "InputMethodRelay.hpp" -enum eClickBehaviorMode -{ +enum eClickBehaviorMode { CLICKMODE_DEFAULT = 0, CLICKMODE_KILL }; -enum eMouseBindMode -{ +enum eMouseBindMode { MBIND_INVALID = -1, MBIND_MOVE = 0, MBIND_RESIZE = 1, @@ -22,8 +20,7 @@ enum eMouseBindMode MBIND_RESIZE_FORCE_RATIO = 3 }; -enum eBorderIconDirection -{ +enum eBorderIconDirection { BORDERICON_NONE, BORDERICON_UP, BORDERICON_DOWN, @@ -118,6 +115,7 @@ class CInputManager { // for dragging floating windows CWindow* currentlyDraggedWindow = nullptr; eMouseBindMode dragMode = MBIND_INVALID; + bool m_bWasDraggingWindow = false; // for refocus to be forced CWindow* m_pForcedFocus = nullptr; diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 4d3200a6..280fe921 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -24,6 +24,7 @@ eDecorationType CHyprGroupBarDecoration::getDecorationType() { constexpr int BAR_INDICATOR_HEIGHT = 3; constexpr int BAR_PADDING_OUTER_VERT = 2; constexpr int BAR_TEXT_PAD = 2; +constexpr int BAR_HORIZONTAL_PADDING = 2; // @@ -93,15 +94,13 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& if (!m_pWindow->m_sSpecialRenderData.decorate) return; - const int PAD = 2; //2px + m_fBarWidth = (m_vLastWindowSize.x - BAR_HORIZONTAL_PADDING * (barsToDraw - 1)) / barsToDraw; - const int BARW = (m_vLastWindowSize.x - PAD * (barsToDraw - 1)) / barsToDraw; - - int xoff = 0; + int xoff = 0; for (int i = 0; i < barsToDraw; ++i) { wlr_box rect = {m_vLastWindowPos.x + xoff - pMonitor->vecPosition.x + offset.x, - m_vLastWindowPos.y - BAR_PADDING_OUTER_VERT - BORDERSIZE - BAR_INDICATOR_HEIGHT - pMonitor->vecPosition.y + offset.y, BARW, BAR_INDICATOR_HEIGHT}; + m_vLastWindowPos.y - BAR_PADDING_OUTER_VERT - BORDERSIZE - BAR_INDICATOR_HEIGHT - pMonitor->vecPosition.y + offset.y, m_fBarWidth, BAR_INDICATOR_HEIGHT}; if (rect.width <= 0 || rect.height <= 0) break; @@ -127,15 +126,15 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[i]->m_szTitle); if (!pTitleTex) - pTitleTex = - m_sTitleTexs.titleTexs - .emplace_back(std::make_unique(m_dwGroupMembers[i], Vector2D{BARW * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale})) - .get(); + pTitleTex = m_sTitleTexs.titleTexs + .emplace_back(std::make_unique(m_dwGroupMembers[i], + Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale})) + .get(); rect.height = (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * 0.8 * pMonitor->scale; rect.y -= rect.height; - rect.width = BARW * pMonitor->scale; + rect.width = m_fBarWidth * pMonitor->scale; refreshGradients(); @@ -148,7 +147,7 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& g_pHyprOpenGL->renderTexture(pTitleTex->tex, &rect, 1.f); } - xoff += PAD + BARW; + xoff += BAR_HORIZONTAL_PADDING + m_fBarWidth; } if (*PRENDERTITLES) @@ -305,3 +304,79 @@ void CHyprGroupBarDecoration::refreshGradients() { bool CHyprGroupBarDecoration::allowsInput() { return true; } + +bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D& pos) { + + if (!(!g_pKeybindManager->m_bGroupsLocked // global group lock disengaged + && ((pDraggedWindow->m_eGroupRules & GROUP_INVADE && pDraggedWindow->m_bFirstMap) // window ignore local group locks, or + || (!m_pWindow->getGroupHead()->m_sGroupData.locked // target unlocked + && !(pDraggedWindow->m_sGroupData.pNextWindow && pDraggedWindow->getGroupHead()->m_sGroupData.locked))) // source unlocked or isn't group + && !pDraggedWindow->m_sGroupData.deny // source is not denied entry + && !(pDraggedWindow->m_eGroupRules & GROUP_BARRED && pDraggedWindow->m_bFirstMap))) // group rule doesn't prevent adding window + return true; + + const float BARRELATIVEX = pos.x - m_vLastWindowPos.x - m_fBarWidth / 2; + const int WINDOWINDEX = BARRELATIVEX < 0 ? -1 : (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); + + CWindow* pWindowInsertAfter = m_pWindow->getGroupWindowByIndex(WINDOWINDEX); + + g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pDraggedWindow); + + pWindowInsertAfter->insertWindowToGroup(pDraggedWindow); + + if (WINDOWINDEX == -1) + std::swap(pDraggedWindow->m_sGroupData.head, pDraggedWindow->m_sGroupData.pNextWindow->m_sGroupData.head); + + m_pWindow->setGroupCurrent(pDraggedWindow); + pDraggedWindow->applyGroupRules(); + pDraggedWindow->updateWindowDecos(); + g_pLayoutManager->getCurrentLayout()->recalculateWindow(pDraggedWindow); + + return false; +} + +void CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, wlr_pointer_button_event* e) { + if (e->state != WLR_BUTTON_PRESSED) + return; + + const float BARRELATIVEX = pos.x - m_vLastWindowPos.x; + const int WINDOWINDEX = (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); + + if (BARRELATIVEX - (m_fBarWidth + BAR_HORIZONTAL_PADDING) * WINDOWINDEX > m_fBarWidth) { + if (!g_pCompositor->isWindowActive(m_pWindow)) + g_pCompositor->focusWindow(m_pWindow); + return; + } + + CWindow* pWindow = m_pWindow->getGroupWindowByIndex(WINDOWINDEX); + + if (pWindow != m_pWindow) + pWindow->setGroupCurrent(pWindow); + + if (!g_pCompositor->isWindowActive(pWindow)) + g_pCompositor->focusWindow(pWindow); +} + +void CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) { + const float BARRELATIVEX = pos.x - m_vLastWindowPos.x; + const int WINDOWINDEX = (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); + + if (BARRELATIVEX - (m_fBarWidth + BAR_HORIZONTAL_PADDING) * WINDOWINDEX > m_fBarWidth) + return; + + CWindow* pWindow = m_pWindow->getGroupWindowByIndex(WINDOWINDEX); + + // hack + g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow); + if (!pWindow->m_bIsFloating) { + const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_bGroupsLocked; + g_pKeybindManager->m_bGroupsLocked = true; + g_pLayoutManager->getCurrentLayout()->onWindowCreated(pWindow); + g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV; + } + + g_pInputManager->currentlyDraggedWindow = pWindow; + + if (!g_pCompositor->isWindowActive(pWindow)) + g_pCompositor->focusWindow(pWindow); +} diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp index 118c7a64..05736d4b 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.hpp +++ b/src/render/decorations/CHyprGroupBarDecoration.hpp @@ -35,6 +35,12 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { virtual bool allowsInput(); + virtual void onBeginWindowDragOnDeco(const Vector2D&); + + virtual bool onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D&); + + virtual void onMouseButtonOnDeco(const Vector2D&, wlr_pointer_button_event*); + private: SWindowDecorationExtents m_seExtents; @@ -45,6 +51,8 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { std::deque m_dwGroupMembers; + float m_fBarWidth; + CTitleTex* textureFromTitle(const std::string&); void invalidateTextures(); diff --git a/src/render/decorations/IHyprWindowDecoration.cpp b/src/render/decorations/IHyprWindowDecoration.cpp index a87c334a..e0868b0b 100644 --- a/src/render/decorations/IHyprWindowDecoration.cpp +++ b/src/render/decorations/IHyprWindowDecoration.cpp @@ -28,3 +28,11 @@ CRegion IHyprWindowDecoration::getWindowDecorationRegion() { bool IHyprWindowDecoration::allowsInput() { return false; } + +void IHyprWindowDecoration::onBeginWindowDragOnDeco(const Vector2D&) {} + +bool IHyprWindowDecoration::onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D&) { + return true; +} + +void IHyprWindowDecoration::onMouseButtonOnDeco(const Vector2D&, wlr_pointer_button_event*) {} diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp index fec7305d..eadc486f 100644 --- a/src/render/decorations/IHyprWindowDecoration.hpp +++ b/src/render/decorations/IHyprWindowDecoration.hpp @@ -39,6 +39,12 @@ class IHyprWindowDecoration { virtual bool allowsInput(); + virtual void onBeginWindowDragOnDeco(const Vector2D&); // called when the user calls the "movewindow" mouse dispatcher on the deco + + virtual bool onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D&); // returns true if the window should be placed by the layout + + virtual void onMouseButtonOnDeco(const Vector2D&, wlr_pointer_button_event*); + private: CWindow* m_pWindow = nullptr; }; From b95c0c318e02a17be3eb7271b02141ab5c22a04f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 29 Oct 2023 20:54:14 +0000 Subject: [PATCH 136/513] renderer: fixup blend disable conditions in renderSurface Fixes #3680 --- src/render/Renderer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index ea662867..f202c2c5 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -76,7 +76,8 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { if (RDATA->dontRound) rounding = 0; - const bool CANDISABLEBLEND = RDATA->alpha >= 1.f && rounding == 0 && surface->opaque; + const bool WINDOWOPAQUE = RDATA->pWindow && RDATA->pWindow->m_pWLSurface.wlr() == surface ? RDATA->pWindow->opaque() : false; + const bool CANDISABLEBLEND = RDATA->alpha * RDATA->fadeAlpha >= 1.f && rounding == 0 && (WINDOWOPAQUE || surface->opaque); if (CANDISABLEBLEND) g_pHyprOpenGL->blend(false); From 935c90915a8a143d1759c2bb6f0593a8aee6812b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 29 Oct 2023 21:21:54 +0000 Subject: [PATCH 137/513] pluginapi: fixup get_hash functions --- src/plugins/PluginAPI.cpp | 4 ++++ src/plugins/PluginAPI.hpp | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/plugins/PluginAPI.cpp b/src/plugins/PluginAPI.cpp index a873644e..1395728d 100644 --- a/src/plugins/PluginAPI.cpp +++ b/src/plugins/PluginAPI.cpp @@ -9,6 +9,10 @@ #include +APICALL const char* __hyprland_api_get_hash() { + return GIT_COMMIT_HASH; +} + APICALL bool HyprlandAPI::registerCallbackStatic(HANDLE handle, const std::string& event, HOOK_CALLBACK_FN* fn) { auto* const PLUGIN = g_pPluginSystem->getPluginByHandle(handle); diff --git a/src/plugins/PluginAPI.hpp b/src/plugins/PluginAPI.hpp index 30c6b4c7..a3792fe9 100644 --- a/src/plugins/PluginAPI.hpp +++ b/src/plugins/PluginAPI.hpp @@ -280,7 +280,11 @@ namespace HyprlandAPI { This function will end up in both hyprland and any/all plugins, and can be found by a simple dlsym() + + _get_hash() is server, + _get_client_hash() is client. */ -APICALL inline EXPORT const char* __hyprland_api_get_hash() { +APICALL EXPORT const char* __hyprland_api_get_hash(); +APICALL inline EXPORT const char* __hyprland_api_get_client_hash() { return GIT_COMMIT_HASH; } From 59d6a12a7e06a579a364ea93eca957a70be74081 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 29 Oct 2023 22:35:26 +0000 Subject: [PATCH 138/513] config: fixup usage of plugin in handles would filter calls to keyword plugin: and stuff --- src/config/ConfigManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 3d4d265a..5d116128 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1384,10 +1384,10 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std:: handleBlurLS(COMMAND, VALUE); else if (COMMAND == "wsbind") handleBindWS(COMMAND, VALUE); + else if (COMMAND == "plugin") + handlePlugin(COMMAND, VALUE); else if (COMMAND.starts_with("env")) handleEnv(COMMAND, VALUE); - else if (COMMAND.starts_with("plugin")) - handlePlugin(COMMAND, VALUE); else { // try config const auto IT = std::find_if(pluginKeywords.begin(), pluginKeywords.end(), [&](const auto& other) { return other.name == COMMAND; }); From 86318ce04f59295175bd3eabedaf5e0f4fa2cc1e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 29 Oct 2023 23:37:12 +0000 Subject: [PATCH 139/513] input: let input-grabbing decos have prio over resize on border --- src/managers/input/InputManager.cpp | 95 ++++++++++++++++++----------- 1 file changed, 58 insertions(+), 37 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 40d25858..09571291 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1621,49 +1621,70 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) { // give a small leeway (10 px) for corner icon const auto CORNER = *PROUNDING + BORDERSIZE + 10; const auto mouseCoords = getMouseCoordsInternal(); - wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; + wlr_box box = w->getWindowMainSurfaceBox(); eBorderIconDirection direction = BORDERICON_NONE; wlr_box boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE), - box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; + box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; - if (!wlr_box_contains_point(&boxFullGrabInput, mouseCoords.x, mouseCoords.y) || (!m_lCurrentlyHeldButtons.empty() && !currentlyDraggedWindow)) { + if (w->hasPopupAt(mouseCoords)) direction = BORDERICON_NONE; - } else if (wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y)) { - if (!w->isInCurvedCorner(mouseCoords.x, mouseCoords.y)) { - direction = BORDERICON_NONE; - } else { - if (mouseCoords.y < box.y + CORNER) { - if (mouseCoords.x < box.x + CORNER) - direction = BORDERICON_UP_LEFT; - else - direction = BORDERICON_UP_RIGHT; - } else { - if (mouseCoords.x < box.x + CORNER) - direction = BORDERICON_DOWN_LEFT; - else - direction = BORDERICON_DOWN_RIGHT; + else if (!wlr_box_contains_point(&boxFullGrabInput, mouseCoords.x, mouseCoords.y) || (!m_lCurrentlyHeldButtons.empty() && !currentlyDraggedWindow)) + direction = BORDERICON_NONE; + else { + + bool onDeco = false; + + for (auto& d : w->m_dWindowDecorations) { + if (!d->allowsInput()) + continue; + + if (d->getWindowDecorationRegion().containsPoint(mouseCoords)) { + onDeco = true; + break; } } - } else { - if (mouseCoords.y < box.y + CORNER) { - if (mouseCoords.x < box.x + CORNER) - direction = BORDERICON_UP_LEFT; - else if (mouseCoords.x > box.x + box.width - CORNER) - direction = BORDERICON_UP_RIGHT; - else - direction = BORDERICON_UP; - } else if (mouseCoords.y > box.y + box.height - CORNER) { - if (mouseCoords.x < box.x + CORNER) - direction = BORDERICON_DOWN_LEFT; - else if (mouseCoords.x > box.x + box.width - CORNER) - direction = BORDERICON_DOWN_RIGHT; - else - direction = BORDERICON_DOWN; - } else { - if (mouseCoords.x < box.x + CORNER) - direction = BORDERICON_LEFT; - else if (mouseCoords.x > box.x + box.width - CORNER) - direction = BORDERICON_RIGHT; + + if (onDeco) + direction = BORDERICON_NONE; + else { + if (wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y)) { + if (!w->isInCurvedCorner(mouseCoords.x, mouseCoords.y)) { + direction = BORDERICON_NONE; + } else { + if (mouseCoords.y < box.y + CORNER) { + if (mouseCoords.x < box.x + CORNER) + direction = BORDERICON_UP_LEFT; + else + direction = BORDERICON_UP_RIGHT; + } else { + if (mouseCoords.x < box.x + CORNER) + direction = BORDERICON_DOWN_LEFT; + else + direction = BORDERICON_DOWN_RIGHT; + } + } + } else { + if (mouseCoords.y < box.y + CORNER) { + if (mouseCoords.x < box.x + CORNER) + direction = BORDERICON_UP_LEFT; + else if (mouseCoords.x > box.x + box.width - CORNER) + direction = BORDERICON_UP_RIGHT; + else + direction = BORDERICON_UP; + } else if (mouseCoords.y > box.y + box.height - CORNER) { + if (mouseCoords.x < box.x + CORNER) + direction = BORDERICON_DOWN_LEFT; + else if (mouseCoords.x > box.x + box.width - CORNER) + direction = BORDERICON_DOWN_RIGHT; + else + direction = BORDERICON_DOWN; + } else { + if (mouseCoords.x < box.x + CORNER) + direction = BORDERICON_LEFT; + else if (mouseCoords.x > box.x + box.width - CORNER) + direction = BORDERICON_RIGHT; + } + } } } From 8e91c038db0f512e5bfe84711ee1a1345055d7a3 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 30 Oct 2023 00:18:40 +0000 Subject: [PATCH 140/513] renderer: use optional for cursor surface storing because nullptr is a valid surface. fixes #3692 --- src/render/Renderer.cpp | 2 +- src/render/Renderer.hpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index f202c2c5..927c589d 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1956,7 +1956,7 @@ void CHyprRenderer::setCursorFromName(const std::string& name) { return; m_sLastCursorData.name = name; - m_sLastCursorData.surf = nullptr; + m_sLastCursorData.surf.reset(); wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, name.c_str()); } diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 859d1d6a..0281d33f 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -84,8 +84,8 @@ class CHyprRenderer { CTimer m_tRenderTimer; struct { - wlr_surface* surf = nullptr; - std::string name; + std::optional surf = nullptr; + std::string name; } m_sLastCursorData; private: From cb6cfde6e82f9b146ba1bd937472aa17ec829167 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 30 Oct 2023 14:49:49 +0000 Subject: [PATCH 141/513] window: update window reported size on damage events --- src/helpers/SubsurfaceTree.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/helpers/SubsurfaceTree.cpp b/src/helpers/SubsurfaceTree.cpp index b0ed0bfa..c3716100 100644 --- a/src/helpers/SubsurfaceTree.cpp +++ b/src/helpers/SubsurfaceTree.cpp @@ -247,6 +247,9 @@ void Events::listener_commitSubsurface(void* owner, void* data) { g_pHyprRenderer->damageSurface(pNode->pSurface->wlr(), lx, ly, SCALE); if (pNode->pWindowOwner) { + // update reported size. Some windows do not send a ::commit afterwards. Odd. + pNode->pWindowOwner->m_vReportedSize = pNode->pWindowOwner->m_vPendingReportedSize; + // tearing: if solitary, redraw it. This still might be a single surface window const auto PMONITOR = g_pCompositor->getMonitorFromID(pNode->pWindowOwner->m_iMonitorID); if (PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->canBeTorn() && PMONITOR->tearingState.canTear && From a1924ae4356657a06e43e740f1cf2e1634fa958d Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Mon, 30 Oct 2023 14:54:12 +0000 Subject: [PATCH 142/513] internal: create canBeGroupedInto() (#3693) modified: src/Window.cpp modified: src/Window.hpp modified: src/layout/DwindleLayout.cpp modified: src/layout/MasterLayout.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp --- src/Window.cpp | 9 +++++++++ src/Window.hpp | 9 ++++----- src/layout/DwindleLayout.cpp | 11 ++--------- src/layout/MasterLayout.cpp | 10 ++-------- src/render/decorations/CHyprGroupBarDecoration.cpp | 7 +------ 5 files changed, 18 insertions(+), 28 deletions(-) diff --git a/src/Window.cpp b/src/Window.cpp index fb46740b..77960dc6 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -767,6 +767,15 @@ int CWindow::getGroupSize() { return size; } +bool CWindow::canBeGroupedInto(CWindow* 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 && 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 +} + CWindow* CWindow::getGroupWindowByIndex(int index) { const int SIZE = getGroupSize(); index = ((index % SIZE) + SIZE) % SIZE; diff --git a/src/Window.hpp b/src/Window.hpp index f856b2a9..624d3325 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -11,16 +11,14 @@ #include "macros.hpp" #include "managers/XWaylandManager.hpp" -enum eIdleInhibitMode -{ +enum eIdleInhibitMode { IDLEINHIBIT_NONE = 0, IDLEINHIBIT_ALWAYS, IDLEINHIBIT_FULLSCREEN, IDLEINHIBIT_FOCUS }; -enum eGroupRules -{ +enum eGroupRules { // effective only during first map, except for _ALWAYS variant GROUP_NONE = 0, GROUP_SET = 1 << 0, // Open as new group or add to focused group @@ -379,6 +377,7 @@ class CWindow { CWindow* getGroupPrevious(); CWindow* getGroupWindowByIndex(int); int getGroupSize(); + bool canBeGroupedInto(CWindow* pWindow); void setGroupCurrent(CWindow* pWindow); void insertWindowToGroup(CWindow* pWindow); void updateGroupOutputs(); @@ -428,4 +427,4 @@ struct std::formatter : std::formatter { std::format_to(out, ", class: {}", g_pXWaylandManager->getAppIDClass(w)); return std::format_to(out, "]"); } -}; \ No newline at end of file +}; diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 984db38d..74277dd4 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -326,15 +326,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire } // if it's a group, add the window - if (OPENINGON->pWindow->m_sGroupData.pNextWindow // target is group - && !g_pKeybindManager->m_bGroupsLocked // global group lock disengaged - && ((pWindow->m_eGroupRules & GROUP_INVADE && pWindow->m_bFirstMap) // window ignore local group locks, or - || (!OPENINGON->pWindow->getGroupHead()->m_sGroupData.locked // target unlocked - && !(pWindow->m_sGroupData.pNextWindow && pWindow->getGroupHead()->m_sGroupData.locked))) // source unlocked or isn't group - && !pWindow->m_sGroupData.deny // source is not denied entry - && !(pWindow->m_eGroupRules & GROUP_BARRED && pWindow->m_bFirstMap) // group rule doesn't prevent adding window - && !m_vOverrideFocalPoint // we are not moving window - ) { + if (OPENINGON->pWindow->m_sGroupData.pNextWindow // target is group + && pWindow->canBeGroupedInto(OPENINGON->pWindow) && !m_vOverrideFocalPoint) { // we are not moving window if (!pWindow->m_sGroupData.pNextWindow) pWindow->m_dWindowDecorations.emplace_back(std::make_unique(pWindow)); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 6ee88512..33b8f62d 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -108,14 +108,8 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc } // if it's a group, add the window - if (OPENINGON && OPENINGON != PNODE && OPENINGON->pWindow->m_sGroupData.pNextWindow // target is group - && !g_pKeybindManager->m_bGroupsLocked // global group lock disengaged - && ((pWindow->m_eGroupRules & GROUP_INVADE && pWindow->m_bFirstMap) // window ignore local group locks, or - || (!OPENINGON->pWindow->getGroupHead()->m_sGroupData.locked // target unlocked - && !(pWindow->m_sGroupData.pNextWindow && pWindow->getGroupHead()->m_sGroupData.locked))) // source unlocked or isn't group - && !pWindow->m_sGroupData.deny // source is not denied entry - && !(pWindow->m_eGroupRules & GROUP_BARRED) // group rule doesn't prevent adding window - ) { + if (OPENINGON && OPENINGON != PNODE && OPENINGON->pWindow->m_sGroupData.pNextWindow // target is group + && pWindow->canBeGroupedInto(OPENINGON->pWindow)) { if (!pWindow->m_sGroupData.pNextWindow) pWindow->m_dWindowDecorations.emplace_back(std::make_unique(pWindow)); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 280fe921..7f9fcde9 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -307,12 +307,7 @@ bool CHyprGroupBarDecoration::allowsInput() { bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D& pos) { - if (!(!g_pKeybindManager->m_bGroupsLocked // global group lock disengaged - && ((pDraggedWindow->m_eGroupRules & GROUP_INVADE && pDraggedWindow->m_bFirstMap) // window ignore local group locks, or - || (!m_pWindow->getGroupHead()->m_sGroupData.locked // target unlocked - && !(pDraggedWindow->m_sGroupData.pNextWindow && pDraggedWindow->getGroupHead()->m_sGroupData.locked))) // source unlocked or isn't group - && !pDraggedWindow->m_sGroupData.deny // source is not denied entry - && !(pDraggedWindow->m_eGroupRules & GROUP_BARRED && pDraggedWindow->m_bFirstMap))) // group rule doesn't prevent adding window + if (!pDraggedWindow->canBeGroupedInto(m_pWindow)) return true; const float BARRELATIVEX = pos.x - m_vLastWindowPos.x - m_fBarWidth / 2; From 4b592d0819e2f4563d59e6cbb2c3c236ec8f23af Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 30 Oct 2023 15:56:02 +0000 Subject: [PATCH 143/513] renderer: properly pass 10-bit formats to opengl --- src/helpers/MiscFunctions.cpp | 12 ++++++++++++ src/helpers/MiscFunctions.hpp | 1 + src/helpers/Monitor.hpp | 1 + src/render/Framebuffer.cpp | 7 +++++-- src/render/Framebuffer.hpp | 2 +- src/render/OpenGL.cpp | 18 +++++++++--------- src/render/Renderer.cpp | 5 ++++- 7 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 3cce73d2..acb9cf20 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -750,4 +750,16 @@ std::vector getBacktrace() { void throwError(const std::string& err) { Debug::log(CRIT, "Critical error thrown: {}", err); throw std::runtime_error(err); +} + +uint32_t drmFormatToGL(uint32_t drm) { + switch (drm) { + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: return GL_RGBA; // doesn't matter, opengl is gucci in this case. + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_XBGR2101010: return GL_RGB10_A2; + default: return GL_RGBA; + } + UNREACHABLE(); + return GL_RGBA; } \ No newline at end of file diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index d489a0cd..499aa90f 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -33,6 +33,7 @@ double normalizeAngleRad(double ang); std::string replaceInString(std::string subject, const std::string& search, const std::string& replace); std::vector getBacktrace(); void throwError(const std::string& err); +uint32_t drmFormatToGL(uint32_t drm); template [[deprecated("use std::format instead")]] std::string getFormat(std::format_string fmt, Args&&... args) { diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 71c84273..5e0df858 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -65,6 +65,7 @@ class CMonitor { bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed. bool createdByUser = false; + uint32_t drmFormat = DRM_FORMAT_INVALID; bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after bool renderingActive = false; diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp index a62ea18a..e1f815ce 100644 --- a/src/render/Framebuffer.cpp +++ b/src/render/Framebuffer.cpp @@ -1,10 +1,13 @@ #include "Framebuffer.hpp" #include "OpenGL.hpp" -bool CFramebuffer::alloc(int w, int h) { +bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { bool firstAlloc = false; RASSERT((w > 1 && h > 1), "cannot alloc a FB with negative / zero size! (attempted {}x{})", w, h); + uint32_t glFormat = drmFormatToGL(drmFormat); + uint32_t glType = glFormat != GL_RGBA ? GL_UNSIGNED_INT_2_10_10_10_REV : GL_UNSIGNED_BYTE; + if (m_iFb == (uint32_t)-1) { firstAlloc = true; glGenFramebuffers(1, &m_iFb); @@ -22,7 +25,7 @@ bool CFramebuffer::alloc(int w, int h) { if (firstAlloc || m_vSize != Vector2D(w, h)) { glBindTexture(GL_TEXTURE_2D, m_cTex.m_iTexID); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexImage2D(GL_TEXTURE_2D, 0, glFormat, w, h, 0, GL_RGBA, glType, 0); glBindFramebuffer(GL_FRAMEBUFFER, m_iFb); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_cTex.m_iTexID, 0); diff --git a/src/render/Framebuffer.hpp b/src/render/Framebuffer.hpp index 9ba3ac05..73b70431 100644 --- a/src/render/Framebuffer.hpp +++ b/src/render/Framebuffer.hpp @@ -7,7 +7,7 @@ class CFramebuffer { public: ~CFramebuffer(); - bool alloc(int w, int h); + bool alloc(int w, int h, uint32_t format = GL_RGBA); void bind(); void release(); void reset(); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 4a5b70dd..d23a1d38 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -130,10 +130,10 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; m_RenderData.pCurrentMonData->offMainFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; - m_RenderData.pCurrentMonData->primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); - m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); - m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); - m_RenderData.pCurrentMonData->offMainFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); + m_RenderData.pCurrentMonData->primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); + m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); + m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); + m_RenderData.pCurrentMonData->offMainFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); createBGTextureForMonitor(pMonitor); } @@ -1139,7 +1139,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() { const auto POUTFB = blurMainFramebufferWithDamage(1, &fakeDamage); // render onto blurFB - m_RenderData.pCurrentMonData->blurFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y); + m_RenderData.pCurrentMonData->blurFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y, m_RenderData.pMonitor->drmFormat); m_RenderData.pCurrentMonData->blurFB.bind(); clear(CColor(0, 0, 0, 0)); @@ -1430,7 +1430,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(CWindow* pWindow, CFramebuffer* pFra pFramebuffer->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; - pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); + pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat); pFramebuffer->bind(); @@ -1488,7 +1488,7 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) { PFRAMEBUFFER->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; - PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); + PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat); PFRAMEBUFFER->bind(); @@ -1533,7 +1533,7 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) { glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y); - PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); + PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat); PFRAMEBUFFER->bind(); @@ -1721,7 +1721,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl void CHyprOpenGLImpl::saveBufferForMirror() { if (!m_RenderData.pCurrentMonData->monitorMirrorFB.isAllocated()) - m_RenderData.pCurrentMonData->monitorMirrorFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y); + m_RenderData.pCurrentMonData->monitorMirrorFB.alloc(m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y, m_RenderData.pMonitor->drmFormat); m_RenderData.pCurrentMonData->monitorMirrorFB.bind(); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 927c589d..912c1bed 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1877,7 +1877,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR }; // clang-format on - bool set10bit = false; + bool set10bit = false; + pMonitor->drmFormat = DRM_FORMAT_INVALID; for (auto& fmt : formats[(int)!pMonitorRule->enable10bit]) { wlr_output_set_render_format(pMonitor->output, fmt.second); @@ -1888,6 +1889,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR Debug::log(LOG, "output {} succeeded basic test on format {}", pMonitor->szName, fmt.first); if (pMonitorRule->enable10bit && fmt.first.contains("101010")) set10bit = true; + + pMonitor->drmFormat = fmt.second; break; } } From 1c9d6b94d178c234cc5174dfe6d2f952cf0438f3 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 30 Oct 2023 16:20:30 +0000 Subject: [PATCH 144/513] renderer: fix small surface's blur region being offset by monitor coords --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 912c1bed..72ad3db7 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -433,7 +433,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall && renderdata.blur) { - wlr_box wb = {renderdata.x, renderdata.y, renderdata.w, renderdata.h}; + wlr_box wb = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h}; scaleBox(&wb, pMonitor->scale); g_pHyprOpenGL->renderRectWithBlur(&wb, CColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1); renderdata.blur = false; From f48b3774a2cfa95105ea4cbe8f05f70a6357a628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= Date: Mon, 30 Oct 2023 18:27:38 +0000 Subject: [PATCH 145/513] nix: use mesonAutoFeatures attribute --- nix/default.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nix/default.nix b/nix/default.nix index d12bc073..a5ddd24c 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -90,8 +90,9 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov then "debug" else "release"; + mesonAutoFeatures = "disabled"; + mesonFlags = builtins.concatLists [ - ["-Dauto_features=disabled"] (lib.optional enableXWayland "-Dxwayland=enabled") (lib.optional legacyRenderer "-Dlegacy_renderer=enabled") (lib.optional withSystemd "-Dsystemd=enabled") From ab5497a0c9e9269b1036a0bede42cbd0bbfd94b9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 30 Oct 2023 19:36:34 +0000 Subject: [PATCH 146/513] input: properly track xdg surfaces' geometry in vectorToSurfaceLocal fixes #3703 --- src/Compositor.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 9b36b338..f1ac7b2b 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -865,10 +865,13 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, CWindow* pWindow }, &iterData); + wlr_box geom = {0}; + wlr_xdg_surface_get_geometry(PSURFACE, &geom); + if (std::get<1>(iterData) == -1337 && std::get<2>(iterData) == -1337) return vec - pWindow->m_vRealPosition.goalv(); - return vec - pWindow->m_vRealPosition.goalv() - Vector2D{std::get<1>(iterData), std::get<2>(iterData)}; + return vec - pWindow->m_vRealPosition.goalv() - Vector2D{std::get<1>(iterData), std::get<2>(iterData)} + Vector2D{geom.x, geom.y}; } CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) { From 6914103289125c4c909c1f17e53f9bdd02a66e62 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 31 Oct 2023 21:45:27 +0000 Subject: [PATCH 147/513] cmake: set asan for only hyprland not others --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 228e40c4..31a1646b 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -116,7 +116,7 @@ if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) message(STATUS "Enabling ASan") target_link_libraries(Hyprland asan) - add_compile_options(-fsanitize=address) + target_compile_options(Hyprland PUBLIC -fsanitize=address) endif() if(USE_TRACY) From 7b32b4214d028a173c8192bddaa9e43503326080 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 1 Nov 2023 01:28:43 +0000 Subject: [PATCH 148/513] layout: avoid redundant size sets on new fullscreen --- src/layout/DwindleLayout.cpp | 5 ++++- src/layout/MasterLayout.cpp | 7 +++++-- src/layout/MasterLayout.hpp | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 74277dd4..ef7fc3c8 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -119,6 +119,9 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for // if user specified them in config const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)); + if (PWINDOW->m_bIsFullscreen && !force) + return; + PWINDOW->updateSpecialRenderData(); static auto* const PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue; @@ -561,7 +564,7 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) { PFULLWINDOW->m_vPosition = fakeNode.position; PFULLWINDOW->m_vSize = fakeNode.size; - applyNodeDataToWindow(&fakeNode); + applyNodeDataToWindow(&fakeNode, true); } return; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 33b8f62d..abc0fe9c 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -566,7 +566,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { } } -void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { +void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode, bool force) { CMonitor* PMONITOR = nullptr; if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) { @@ -596,6 +596,9 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { // if user specified them in config const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)); + if (PWINDOW->m_bIsFullscreen && !force) + return; + PWINDOW->updateSpecialRenderData(); static auto* const PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue; @@ -889,7 +892,7 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen pWindow->m_vPosition = fakeNode.position; pWindow->m_vSize = fakeNode.size; - applyNodeDataToWindow(&fakeNode); + applyNodeDataToWindow(&fakeNode, true); } } diff --git a/src/layout/MasterLayout.hpp b/src/layout/MasterLayout.hpp index f220bd7b..f0f72d6b 100644 --- a/src/layout/MasterLayout.hpp +++ b/src/layout/MasterLayout.hpp @@ -76,7 +76,7 @@ class CHyprMasterLayout : public IHyprLayout { void buildOrientationCycleVectorFromEOperation(std::vector& cycle); void runOrientationCycle(SLayoutMessageHeader& header, CVarList* vars, int next); int getNodesOnWorkspace(const int&); - void applyNodeDataToWindow(SMasterNodeData*); + void applyNodeDataToWindow(SMasterNodeData*, bool force = false); SMasterNodeData* getNodeFromWindow(CWindow*); SMasterNodeData* getMasterNodeOnWorkspace(const int&); SMasterWorkspaceData* getMasterWorkspaceData(const int&); From 21e9313c100e005ec2a9a5100c29258a2885546b Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Wed, 1 Nov 2023 18:53:36 +0000 Subject: [PATCH 149/513] Core: various unsafe state improvements (#3713) Fixes #3637 --- src/Compositor.cpp | 59 ++++++++++++++++++++++++------------ src/Compositor.hpp | 4 ++- src/Window.cpp | 3 ++ src/config/ConfigManager.cpp | 8 ++--- src/debug/HyprCtl.cpp | 2 +- src/events/Monitors.cpp | 54 ++++++++++----------------------- src/events/Windows.cpp | 2 +- src/helpers/Monitor.cpp | 53 +++++++++++++++++--------------- src/helpers/Monitor.hpp | 44 +++++++++++++-------------- src/protocols/XDGOutput.cpp | 20 ++++++------ 10 files changed, 128 insertions(+), 121 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index f1ac7b2b..681cbf86 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -463,6 +463,25 @@ void CCompositor::removeLockFile() { std::filesystem::remove(PATH); } +void CCompositor::prepareFallbackOutput() { + // create a backup monitor + wlr_backend* headless = nullptr; + wlr_multi_for_each_backend( + m_sWLRBackend, + [](wlr_backend* b, void* data) { + if (wlr_backend_is_headless(b)) + *((wlr_backend**)data) = b; + }, + &headless); + + if (!headless) { + Debug::log(WARN, "Unsafe state will be ineffective, no fallback output"); + return; + } + + wlr_headless_add_output(headless, 1920, 1080); +} + void CCompositor::startCompositor() { initAllSignals(); @@ -514,6 +533,8 @@ void CCompositor::startCompositor() { throwError("The backend could not start!"); } + prepareFallbackOutput(); + g_pHyprRenderer->setCursorFromName("left_ptr"); #ifdef USES_SYSTEMD @@ -2657,24 +2678,10 @@ void CCompositor::enterUnsafeState() { Debug::log(LOG, "Entering unsafe state"); + if (!m_pUnsafeOutput->m_bEnabled) + m_pUnsafeOutput->onConnect(false); + m_bUnsafeState = true; - - // create a backup monitor - wlr_backend* headless = nullptr; - wlr_multi_for_each_backend( - m_sWLRBackend, - [](wlr_backend* b, void* data) { - if (wlr_backend_is_headless(b)) - *((wlr_backend**)data) = b; - }, - &headless); - - if (!headless) { - Debug::log(WARN, "Entering an unsafe state without a headless backend"); - return; - } - - m_pUnsafeOutput = wlr_headless_add_output(headless, 1920, 1080); } void CCompositor::leaveUnsafeState() { @@ -2685,10 +2692,22 @@ void CCompositor::leaveUnsafeState() { m_bUnsafeState = false; - if (m_pUnsafeOutput) - wlr_output_destroy(m_pUnsafeOutput); + CMonitor* pNewMonitor = nullptr; + for (auto& pMonitor : m_vMonitors) { + if (pMonitor->output != m_pUnsafeOutput->output) { + pNewMonitor = pMonitor.get(); + break; + } + } - m_pUnsafeOutput = nullptr; + RASSERT(pNewMonitor, "Tried to leave unsafe without a monitor"); + + if (m_pUnsafeOutput->m_bEnabled) + m_pUnsafeOutput->onDisconnect(); + + for (auto& m : m_vMonitors) { + scheduleFrameForMonitor(m.get()); + } } void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scale) { diff --git a/src/Compositor.hpp b/src/Compositor.hpp index ae536c91..59fc9136 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -121,7 +121,8 @@ class CCompositor { bool m_bSessionActive = true; bool m_bDPMSStateON = true; bool m_bUnsafeState = false; // unsafe state is when there is no monitors. - wlr_output* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state + bool m_bNextIsUnsafe = false; // because wlroots + CMonitor* m_pUnsafeOutput = nullptr; // fallback output for the unsafe state bool m_bIsShuttingDown = false; // ------------------------------------------------- // @@ -215,6 +216,7 @@ class CCompositor { void initAllSignals(); void setRandomSplash(); void initManagers(eManagersInitStage stage); + void prepareFallbackOutput(); uint64_t m_iHyprlandPID = 0; }; diff --git a/src/Window.cpp b/src/Window.cpp index 77960dc6..2f0809bf 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -223,6 +223,9 @@ pid_t CWindow::getPID() { wl_client_get_credentials(wl_resource_get_client(m_uSurface.xdg->resource), &PID, nullptr, nullptr); } else { + if (!m_bIsMapped || !m_bMappedX11) + return -1; + PID = m_uSurface.xwayland->pid; } diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 5d116128..e016ba75 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2066,7 +2066,7 @@ void CConfigManager::performMonitorReload() { bool overAgain = false; for (auto& m : g_pCompositor->m_vRealMonitors) { - if (!m->output) + if (!m->output || m->isUnsafeFallback) continue; auto rule = getMonitorRuleFor(m->szName, m->output->description ? m->output->description : ""); @@ -2147,15 +2147,13 @@ bool CConfigManager::shouldBlurLS(const std::string& ns) { void CConfigManager::ensureMonitorStatus() { for (auto& rm : g_pCompositor->m_vRealMonitors) { - if (!rm->output) + if (!rm->output || rm->isUnsafeFallback) continue; auto rule = getMonitorRuleFor(rm->szName, rm->output->description ? rm->output->description : ""); - if (rule.disabled == rm->m_bEnabled) { - rm->m_pThisWrap = &rm; + if (rule.disabled == rm->m_bEnabled) g_pHyprRenderer->applyMonitorRule(rm.get(), &rule); - } } } diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index e7191ae1..b274b244 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -231,7 +231,7 @@ static std::string getWorkspaceData(CWorkspace* w, HyprCtl::eHyprCtlOutputFormat "lastwindowtitle": "{}" }})#", w->m_iID, escapeJSONStrings(w->m_szName), escapeJSONStrings(PMONITOR ? PMONITOR->szName : "?"), - escapeJSONStrings(PMONITOR ? std::to_string(PMONITOR->ID) : "undefined"), g_pCompositor->getWindowsOnWorkspace(w->m_iID), + escapeJSONStrings(PMONITOR ? std::to_string(PMONITOR->ID) : "null"), g_pCompositor->getWindowsOnWorkspace(w->m_iID), ((int)w->m_bHasFullscreenWindow == 1 ? "true" : "false"), (uintptr_t)PLASTW, PLASTW ? escapeJSONStrings(PLASTW->m_szTitle) : ""); } else { return std::format("workspace ID {} ({}) on monitor {}:\n\tmonitorID: {}\n\twindows: {}\n\thasfullscreen: {}\n\tlastwindow: 0x{:x}\n\tlastwindowtitle: {}\n\n", w->m_iID, diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index fa36c53c..f6375edd 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -67,52 +67,31 @@ void Events::listener_newOutput(wl_listener* listener, void* data) { return; } - if (g_pCompositor->m_bUnsafeState) - Debug::log(WARN, "Recovering from an unsafe state. May you be lucky."); - // add it to real std::shared_ptr* PNEWMONITORWRAP = nullptr; PNEWMONITORWRAP = &g_pCompositor->m_vRealMonitors.emplace_back(std::make_shared()); + if (std::string("HEADLESS-1") == OUTPUT->name) + g_pCompositor->m_pUnsafeOutput = PNEWMONITORWRAP->get(); - (*PNEWMONITORWRAP)->ID = g_pCompositor->getNextAvailableMonitorID(OUTPUT->name); + (*PNEWMONITORWRAP)->output = OUTPUT; + const bool FALLBACK = g_pCompositor->m_pUnsafeOutput ? OUTPUT == g_pCompositor->m_pUnsafeOutput->output : false; + (*PNEWMONITORWRAP)->ID = FALLBACK ? -1 : g_pCompositor->getNextAvailableMonitorID(OUTPUT->name); + const auto PNEWMONITOR = PNEWMONITORWRAP->get(); + PNEWMONITOR->isUnsafeFallback = FALLBACK; - const auto PNEWMONITOR = PNEWMONITORWRAP->get(); + if (!FALLBACK) + PNEWMONITOR->onConnect(false); - PNEWMONITOR->output = OUTPUT; - PNEWMONITOR->m_pThisWrap = PNEWMONITORWRAP; + if (!PNEWMONITOR->m_bEnabled || FALLBACK) + return; - PNEWMONITOR->onConnect(false); + // ready to process if we have a real monitor if ((!g_pHyprRenderer->m_pMostHzMonitor || PNEWMONITOR->refreshRate > g_pHyprRenderer->m_pMostHzMonitor->refreshRate) && PNEWMONITOR->m_bEnabled) g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR; - // wlroots will instantly call this handler before we get a return to the wlr_output* in CCompositor::enterUnsafeState - const bool PROBABLYFALLBACK = (g_pCompositor->m_bUnsafeState && !g_pCompositor->m_pUnsafeOutput) || OUTPUT == g_pCompositor->m_pUnsafeOutput; - - // ready to process if we have a real monitor - if (PNEWMONITOR->m_bEnabled && !PROBABLYFALLBACK) { - // leave unsafe state - if (g_pCompositor->m_bUnsafeState) { - // recover workspaces - std::vector wsp; - for (auto& ws : g_pCompositor->m_vWorkspaces) { - wsp.push_back(ws.get()); - } - for (auto& ws : wsp) { - // because this can realloc the vec - g_pCompositor->moveWorkspaceToMonitor(ws, PNEWMONITOR); - } - - g_pHyprRenderer->m_pMostHzMonitor = PNEWMONITOR; - - const auto POS = PNEWMONITOR->middle(); - if (g_pCompositor->m_sSeat.mouse) - wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, POS.x, POS.y); - } - - g_pCompositor->m_bReadyToProcess = true; - } + g_pCompositor->m_bReadyToProcess = true; g_pConfigManager->m_bWantsMonitorReload = true; g_pCompositor->scheduleFrameForMonitor(PNEWMONITOR); @@ -138,7 +117,9 @@ void Events::listener_monitorFrame(void* owner, void* data) { if ((g_pCompositor->m_sWLRSession && !g_pCompositor->m_sWLRSession->active) || !g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) { Debug::log(WARN, "Attempted to render frame on inactive session!"); - if (g_pCompositor->m_bUnsafeState && PMONITOR->output != g_pCompositor->m_pUnsafeOutput) { + if (g_pCompositor->m_bUnsafeState && std::ranges::any_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& m) { + return m->output != g_pCompositor->m_pUnsafeOutput->output; + })) { // restore from unsafe state g_pCompositor->leaveUnsafeState(); } @@ -218,9 +199,6 @@ void Events::listener_monitorDestroy(void* owner, void* data) { pMonitor->output = nullptr; pMonitor->m_bRenderingInitPassed = false; - if (g_pCompositor->m_pUnsafeOutput == OUTPUT) - g_pCompositor->m_pUnsafeOutput = nullptr; - Debug::log(LOG, "Removing monitor {} from realMonitors", pMonitor->szName); std::erase_if(g_pCompositor->m_vRealMonitors, [&](std::shared_ptr& el) { return el.get() == pMonitor; }); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index c0910abe..25b54c6c 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -851,8 +851,8 @@ void Events::listener_destroyWindow(void* owner, void* data) { PWINDOW->m_bReadyToDelete = true; if (!PWINDOW->m_bFadingOut) { - g_pCompositor->removeWindowFromVectorSafe(PWINDOW); // most likely X11 unmanaged or sumn Debug::log(LOG, "Unmapped {} removed instantly", PWINDOW); + g_pCompositor->removeWindowFromVectorSafe(PWINDOW); // most likely X11 unmanaged or sumn } } diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index e96da35c..6d6b40e0 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -109,20 +109,20 @@ void CMonitor::onConnect(bool noRule) { m_bRenderingInitPassed = true; } - if (!m_pThisWrap) { + std::shared_ptr* thisWrapper = nullptr; - // find the wrap - for (auto& m : g_pCompositor->m_vRealMonitors) { - if (m->ID == ID) { - m_pThisWrap = &m; - break; - } + // find the wrap + for (auto& m : g_pCompositor->m_vRealMonitors) { + if (m->ID == ID) { + thisWrapper = &m; + break; } } - if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end()) { - g_pCompositor->m_vMonitors.push_back(*m_pThisWrap); - } + RASSERT(thisWrapper->get(), "CMonitor::onConnect: Had no wrapper???"); + + if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end()) + g_pCompositor->m_vMonitors.push_back(*thisWrapper); m_bEnabled = true; @@ -132,6 +132,8 @@ void CMonitor::onConnect(bool noRule) { if (!noRule) g_pHyprRenderer->applyMonitorRule(this, &monitorRule, true); + wlr_output_commit(output); + wlr_damage_ring_set_bounds(&damage, vecTransformedSize.x, vecTransformedSize.y); wlr_xcursor_manager_load(g_pCompositor->m_sWLRXCursorMgr, scale); @@ -152,8 +154,6 @@ void CMonitor::onConnect(bool noRule) { if (scale < 0.1) scale = getDefaultScale(); - m_pThisWrap = nullptr; - forceFullFrames = 3; // force 3 full frames to make sure there is no blinking due to double-buffering. // @@ -184,6 +184,8 @@ void CMonitor::onConnect(bool noRule) { g_pCompositor->setActiveMonitor(this); renderTimer = wl_event_loop_add_timer(g_pCompositor->m_sWLEventLoop, ratHandler, this); + + g_pCompositor->scheduleFrameForMonitor(this); } void CMonitor::onDisconnect() { @@ -221,9 +223,6 @@ void CMonitor::onDisconnect() { g_pConfigManager->m_bWantsMonitorReload = true; } - m_bEnabled = false; - m_bRenderingInitPassed = false; - hyprListener_monitorFrame.removeCallback(); hyprListener_monitorDamage.removeCallback(); hyprListener_monitorNeedsFrame.removeCallback(); @@ -248,6 +247,9 @@ void CMonitor::onDisconnect() { g_pCompositor->enterUnsafeState(); } + m_bEnabled = false; + m_bRenderingInitPassed = false; + if (BACKUPMON) { // snap cursor wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, BACKUPMON->vecPosition.x + BACKUPMON->vecTransformedSize.x / 2.f, @@ -256,7 +258,7 @@ void CMonitor::onDisconnect() { // move workspaces std::deque wspToMove; for (auto& w : g_pCompositor->m_vWorkspaces) { - if (w->m_iMonitorID == ID) { + if (w->m_iMonitorID == ID || !g_pCompositor->getMonitorFromID(w->m_iMonitorID)) { wspToMove.push_back(w.get()); } } @@ -414,19 +416,22 @@ void CMonitor::setMirror(const std::string& mirrorOf) { vecPosition = RULE.offset; // push to mvmonitors - if (!m_pThisWrap) { - // find the wrap - for (auto& m : g_pCompositor->m_vRealMonitors) { - if (m->ID == ID) { - m_pThisWrap = &m; - break; - } + + std::shared_ptr* thisWrapper = nullptr; + + // find the wrap + for (auto& m : g_pCompositor->m_vRealMonitors) { + if (m->ID == ID) { + thisWrapper = &m; + break; } } + RASSERT(thisWrapper->get(), "CMonitor::setMirror: Had no wrapper???"); + if (std::find_if(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), [&](auto& other) { return other.get() == this; }) == g_pCompositor->m_vMonitors.end()) { - g_pCompositor->m_vMonitors.push_back(*m_pThisWrap); + g_pCompositor->m_vMonitors.push_back(*thisWrapper); } setupDefaultWS(RULE); diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 5e0df858..5e861b50 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -61,11 +61,12 @@ class CMonitor { bool gammaChanged = false; float xwaylandScale = 1.f; - bool dpmsStatus = true; - bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. - bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed. - bool createdByUser = false; - uint32_t drmFormat = DRM_FORMAT_INVALID; + bool dpmsStatus = true; + bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. + bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed. + bool createdByUser = false; + uint32_t drmFormat = DRM_FORMAT_INVALID; + bool isUnsafeFallback = false; bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after bool renderingActive = false; @@ -108,24 +109,23 @@ class CMonitor { DYNLISTENER(monitorBind); // methods - void onConnect(bool noRule); - void onDisconnect(); - void addDamage(const pixman_region32_t* rg); - void addDamage(const CRegion* rg); - void addDamage(const wlr_box* box); - void setMirror(const std::string&); - bool isMirror(); - float getDefaultScale(); - void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false); - void changeWorkspace(const int& id, bool internal = false); - void setSpecialWorkspace(CWorkspace* const pWorkspace); - void setSpecialWorkspace(const int& id); - void moveTo(const Vector2D& pos); - Vector2D middle(); + void onConnect(bool noRule); + void onDisconnect(); + void addDamage(const pixman_region32_t* rg); + void addDamage(const CRegion* rg); + void addDamage(const wlr_box* box); + void setMirror(const std::string&); + bool isMirror(); + float getDefaultScale(); + void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false); + void changeWorkspace(const int& id, bool internal = false); + void setSpecialWorkspace(CWorkspace* const pWorkspace); + void setSpecialWorkspace(const int& id); + void moveTo(const Vector2D& pos); + Vector2D middle(); - std::shared_ptr* m_pThisWrap = nullptr; - bool m_bEnabled = false; - bool m_bRenderingInitPassed = false; + bool m_bEnabled = false; + bool m_bRenderingInitPassed = false; // For the list lookup diff --git a/src/protocols/XDGOutput.cpp b/src/protocols/XDGOutput.cpp index 2ef0c3a6..49845b94 100644 --- a/src/protocols/XDGOutput.cpp +++ b/src/protocols/XDGOutput.cpp @@ -72,15 +72,9 @@ CXDGOutputProtocol::CXDGOutputProtocol(const wl_interface* iface, const int& ver } void CXDGOutputProtocol::onManagerGetXDGOutput(wl_client* client, wl_resource* resource, uint32_t id, wl_resource* outputResource) { - const auto OUTPUT = wlr_output_from_resource(outputResource); + const auto OUTPUT = wlr_output_from_resource(outputResource); - if (!OUTPUT) - return; - - const auto PMONITOR = g_pCompositor->getMonitorFromOutput(OUTPUT); - - if (!PMONITOR) - return; + const auto PMONITOR = g_pCompositor->getMonitorFromOutput(OUTPUT); SXDGOutput* pXDGOutput = m_vXDGOutputs.emplace_back(std::make_unique(PMONITOR)).get(); #ifndef NO_XWAYLAND @@ -99,6 +93,10 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(wl_client* client, wl_resource* r pXDGOutput->resource->setImplementation(&OUTPUT_IMPL, nullptr); pXDGOutput->resource->setData(this); + + if (!PMONITOR) + return; + const auto XDGVER = pXDGOutput->resource->version(); if (XDGVER >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) @@ -116,7 +114,7 @@ void CXDGOutputProtocol::onManagerGetXDGOutput(wl_client* client, wl_resource* r void CXDGOutputProtocol::updateOutputDetails(SXDGOutput* pOutput) { static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue; - if (!pOutput->resource->good()) + if (!pOutput->resource->good() || !pOutput->monitor) return; const auto POS = pOutput->isXWayland ? pOutput->monitor->vecXWaylandPosition : pOutput->monitor->vecPosition; @@ -133,6 +131,10 @@ void CXDGOutputProtocol::updateOutputDetails(SXDGOutput* pOutput) { void CXDGOutputProtocol::updateAllOutputs() { for (auto& o : m_vXDGOutputs) { + + if (!o->monitor) + continue; + updateOutputDetails(o.get()); wlr_output_schedule_done(o->monitor->output); From c44e255194c8cc275e31e62277a8a52143e31881 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Wed, 1 Nov 2023 19:13:39 +0000 Subject: [PATCH 150/513] group: fixes for dragging groups onto groupbars (#3708) * fixes for dragging groups onto groupbars modified: src/render/decorations/CHyprGroupBarDecoration.cpp * use onWindowRemoved() modified: src/render/decorations/CHyprGroupBarDecoration.cpp --- .../decorations/CHyprGroupBarDecoration.cpp | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 7f9fcde9..3e3075ea 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -314,13 +314,45 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(CWindow* pDraggedWindow, con const int WINDOWINDEX = BARRELATIVEX < 0 ? -1 : (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); CWindow* pWindowInsertAfter = m_pWindow->getGroupWindowByIndex(WINDOWINDEX); + CWindow* pWindowInsertEnd = pWindowInsertAfter->m_sGroupData.pNextWindow; + CWindow* pDraggedHead = pDraggedWindow->m_sGroupData.pNextWindow ? pDraggedWindow->getGroupHead() : pDraggedWindow; - g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pDraggedWindow); + if (pDraggedWindow->m_sGroupData.pNextWindow) { + + // stores group data + std::vector members; + CWindow* curr = pDraggedHead; + const bool WASLOCKED = pDraggedHead->m_sGroupData.locked; + do { + members.push_back(curr); + curr = curr->m_sGroupData.pNextWindow; + } while (curr != members[0]); + + // removes all windows + for (CWindow* w : members) { + w->m_sGroupData.pNextWindow = nullptr; + w->m_sGroupData.head = false; + w->m_sGroupData.locked = false; + g_pLayoutManager->getCurrentLayout()->onWindowRemoved(w); + } + + // restores the group + for (auto it = members.begin(); it != members.end(); ++it) { + if (std::next(it) != members.end()) + (*it)->m_sGroupData.pNextWindow = *std::next(it); + else + (*it)->m_sGroupData.pNextWindow = members[0]; + } + members[0]->m_sGroupData.head = true; + members[0]->m_sGroupData.locked = WASLOCKED; + } else { + g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pDraggedWindow); + } pWindowInsertAfter->insertWindowToGroup(pDraggedWindow); if (WINDOWINDEX == -1) - std::swap(pDraggedWindow->m_sGroupData.head, pDraggedWindow->m_sGroupData.pNextWindow->m_sGroupData.head); + std::swap(pDraggedHead->m_sGroupData.head, pWindowInsertEnd->m_sGroupData.head); m_pWindow->setGroupCurrent(pDraggedWindow); pDraggedWindow->applyGroupRules(); From a4db48b46b9b92b5a04b1f34490cb38802942656 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 1 Nov 2023 19:50:32 +0000 Subject: [PATCH 151/513] input: simulate mouse movement to fix focus on open/close window fixes #3679 --- src/events/Windows.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 25b54c6c..e2ff6cc0 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -648,6 +648,8 @@ void Events::listener_mapWindow(void* owner, void* data) { g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale); g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform); + + g_pInputManager->simulateMouseMovement(); } void Events::listener_unmapWindow(void* owner, void* data) { @@ -735,13 +737,10 @@ void Events::listener_unmapWindow(void* owner, void* data) { Debug::log(LOG, "On closed window, new focused candidate is {}", PWINDOWCANDIDATE); - if (PWINDOWCANDIDATE != g_pCompositor->m_pLastWindow) { - if (!PWINDOWCANDIDATE) - g_pInputManager->simulateMouseMovement(); - else - g_pCompositor->focusWindow(PWINDOWCANDIDATE); - } else - g_pInputManager->simulateMouseMovement(); + if (PWINDOWCANDIDATE != g_pCompositor->m_pLastWindow && PWINDOWCANDIDATE) + g_pCompositor->focusWindow(PWINDOWCANDIDATE); + + g_pInputManager->simulateMouseMovement(); // CWindow::onUnmap will remove this window's active status, but we can't really do it above. if (PWINDOW == g_pCompositor->m_pLastWindow || !g_pCompositor->m_pLastWindow) { From 062f749450da9d280f85d3052d7f8bc9b70db62b Mon Sep 17 00:00:00 2001 From: Dashie Date: Wed, 1 Nov 2023 21:31:52 +0100 Subject: [PATCH 152/513] xdg: send unconstrain events after a popup reposition (#3716) * fix: Use unconstrain_from_box after reposition request * chore: Remove unused include * chore: remove variable specifier --- src/events/Popups.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/events/Popups.cpp b/src/events/Popups.cpp index 570963d9..559c8410 100644 --- a/src/events/Popups.cpp +++ b/src/events/Popups.cpp @@ -185,6 +185,12 @@ void Events::listener_repositionPopupXDG(void* owner, void* data) { PPOPUP->lastPos = {lx - extents.x, ly - extents.y}; PPOPUP->repositionRequested = true; + + const auto PMONITOR = g_pCompositor->m_pLastMonitor; + + wlr_box box = {PMONITOR->vecPosition.x - lx + PPOPUP->popup->current.geometry.x, PMONITOR->vecPosition.y - ly + PPOPUP->popup->current.geometry.y, PMONITOR->vecSize.x, + PMONITOR->vecSize.y}; + wlr_xdg_popup_unconstrain_from_box(PPOPUP->popup, &box); } void Events::listener_unmapPopupXDG(void* owner, void* data) { From ef90d1eaaf3e246aa89d1e645192da794740156d Mon Sep 17 00:00:00 2001 From: q234rty Date: Wed, 1 Nov 2023 23:20:51 +0800 Subject: [PATCH 153/513] Map cmake None to meson's plain empty is not a build type that exists in meson. I have no idea why I typed "empty" in #3614 ... Fixes: ba5f1d87838978ae92d4989545a083e28ef58d6f --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 31a1646b..dfe3c456 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,7 +45,7 @@ if(CMAKE_BUILD_TYPE) elseif(BUILDTYPE_LOWER STREQUAL "minsizerel") set(BUILDTYPE_LOWER "minsize") elseif(BUILDTYPE_LOWER STREQUAL "none") - set(BUILDTYPE_LOWER "empty") + set(BUILDTYPE_LOWER "plain") else() set(BUILDTYPE_LOWER "release") endif() From f10996b5753bfc854b019f6889d6bc0c91961e3f Mon Sep 17 00:00:00 2001 From: thejch <66577496+thejch@users.noreply.github.com> Date: Thu, 2 Nov 2023 10:20:32 -0700 Subject: [PATCH 154/513] master: fix moving window between monitors (#3721) --- src/layout/MasterLayout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index abc0fe9c..b5917eeb 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -94,7 +94,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); - if (g_pInputManager->m_bWasDraggingWindow) { + if (g_pInputManager->m_bWasDraggingWindow && OPENINGON) { for (auto& wd : OPENINGON->pWindow->m_dWindowDecorations) { if (!wd->allowsInput()) continue; From ba9e7814b0e02be251ff6172d644de59cf0170de Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 2 Nov 2023 21:36:16 +0000 Subject: [PATCH 155/513] input: simulate movement only if mouse is over in open/close window fixes #3726 --- src/events/Windows.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index e2ff6cc0..ce65fa72 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -649,7 +649,8 @@ void Events::listener_mapWindow(void* owner, void* data) { g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale); g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform); - g_pInputManager->simulateMouseMovement(); + if (g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal()) == g_pCompositor->m_pLastWindow) + g_pInputManager->simulateMouseMovement(); } void Events::listener_unmapWindow(void* owner, void* data) { @@ -740,7 +741,8 @@ void Events::listener_unmapWindow(void* owner, void* data) { if (PWINDOWCANDIDATE != g_pCompositor->m_pLastWindow && PWINDOWCANDIDATE) g_pCompositor->focusWindow(PWINDOWCANDIDATE); - g_pInputManager->simulateMouseMovement(); + if (g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal()) == PWINDOWCANDIDATE) + g_pInputManager->simulateMouseMovement(); // CWindow::onUnmap will remove this window's active status, but we can't really do it above. if (PWINDOW == g_pCompositor->m_pLastWindow || !g_pCompositor->m_pLastWindow) { From 88b47dfa833db2d230a2d6e6bbbf92c69afbdc28 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 2 Nov 2023 23:29:47 +0000 Subject: [PATCH 156/513] xdg: use std::ceil for sending scale to surfaces fixes #3724 --- src/Compositor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 681cbf86..f8d61501 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2712,7 +2712,7 @@ void CCompositor::leaveUnsafeState() { void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scale) { g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(pSurface, scale); - wlr_surface_set_preferred_buffer_scale(pSurface, scale); + wlr_surface_set_preferred_buffer_scale(pSurface, static_cast(std::ceil(scale))); } void CCompositor::setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform) { From 0f6e53079864d411aa2de3262ba4c01eeeec4f5b Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 3 Nov 2023 12:19:23 +0000 Subject: [PATCH 157/513] layout: better storage for no fullscreen checks var fixes #3731 --- src/layout/DwindleLayout.cpp | 17 +++++++++-------- src/layout/DwindleLayout.hpp | 2 ++ src/layout/MasterLayout.cpp | 19 ++++++++++--------- src/layout/MasterLayout.hpp | 13 ++++++++----- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index ef7fc3c8..30568375 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -119,7 +119,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for // if user specified them in config const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)); - if (PWINDOW->m_bIsFullscreen && !force) + if (PWINDOW->m_bIsFullscreen && !pNode->ignoreFullscreenChecks) return; PWINDOW->updateSpecialRenderData(); @@ -557,14 +557,15 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) { PFULLWINDOW->m_vRealSize = PMONITOR->vecSize; } else if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) { SDwindleNodeData fakeNode; - fakeNode.pWindow = PFULLWINDOW; - fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; - fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight; - fakeNode.workspaceID = PWORKSPACE->m_iID; - PFULLWINDOW->m_vPosition = fakeNode.position; - PFULLWINDOW->m_vSize = fakeNode.size; + fakeNode.pWindow = PFULLWINDOW; + fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; + fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight; + fakeNode.workspaceID = PWORKSPACE->m_iID; + PFULLWINDOW->m_vPosition = fakeNode.position; + PFULLWINDOW->m_vSize = fakeNode.size; + fakeNode.ignoreFullscreenChecks = true; - applyNodeDataToWindow(&fakeNode, true); + applyNodeDataToWindow(&fakeNode); } return; diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp index 47818536..7db9066f 100644 --- a/src/layout/DwindleLayout.hpp +++ b/src/layout/DwindleLayout.hpp @@ -30,6 +30,8 @@ struct SDwindleNodeData { bool valid = true; + bool ignoreFullscreenChecks = false; + // For list lookup bool operator==(const SDwindleNodeData& rhs) const { return pWindow == rhs.pWindow && workspaceID == rhs.workspaceID && position == rhs.position && size == rhs.size && pParent == rhs.pParent && diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index b5917eeb..be8da75e 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -566,7 +566,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { } } -void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode, bool force) { +void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { CMonitor* PMONITOR = nullptr; if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) { @@ -596,7 +596,7 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode, bool force // if user specified them in config const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)); - if (PWINDOW->m_bIsFullscreen && !force) + if (PWINDOW->m_bIsFullscreen && !pNode->ignoreFullscreenChecks) return; PWINDOW->updateSpecialRenderData(); @@ -885,14 +885,15 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen // To keep consistent with the settings without C+P code SMasterNodeData fakeNode; - fakeNode.pWindow = pWindow; - fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; - fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight; - fakeNode.workspaceID = pWindow->m_iWorkspaceID; - pWindow->m_vPosition = fakeNode.position; - pWindow->m_vSize = fakeNode.size; + fakeNode.pWindow = pWindow; + fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; + fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight; + fakeNode.workspaceID = pWindow->m_iWorkspaceID; + pWindow->m_vPosition = fakeNode.position; + pWindow->m_vSize = fakeNode.size; + fakeNode.ignoreFullscreenChecks = true; - applyNodeDataToWindow(&fakeNode, true); + applyNodeDataToWindow(&fakeNode); } } diff --git a/src/layout/MasterLayout.hpp b/src/layout/MasterLayout.hpp index f0f72d6b..e316556a 100644 --- a/src/layout/MasterLayout.hpp +++ b/src/layout/MasterLayout.hpp @@ -10,8 +10,7 @@ enum eFullscreenMode : int8_t; //orientation determines which side of the screen the master area resides -enum eOrientation : uint8_t -{ +enum eOrientation : uint8_t { ORIENTATION_LEFT = 0, ORIENTATION_TOP, ORIENTATION_RIGHT, @@ -32,7 +31,10 @@ struct SMasterNodeData { int workspaceID = -1; - bool operator==(const SMasterNodeData& rhs) const { + bool ignoreFullscreenChecks = false; + + // + bool operator==(const SMasterNodeData& rhs) const { return pWindow == rhs.pWindow; } }; @@ -41,7 +43,8 @@ struct SMasterWorkspaceData { int workspaceID = -1; eOrientation orientation = ORIENTATION_LEFT; - bool operator==(const SMasterWorkspaceData& rhs) const { + // + bool operator==(const SMasterWorkspaceData& rhs) const { return workspaceID == rhs.workspaceID; } }; @@ -76,7 +79,7 @@ class CHyprMasterLayout : public IHyprLayout { void buildOrientationCycleVectorFromEOperation(std::vector& cycle); void runOrientationCycle(SLayoutMessageHeader& header, CVarList* vars, int next); int getNodesOnWorkspace(const int&); - void applyNodeDataToWindow(SMasterNodeData*, bool force = false); + void applyNodeDataToWindow(SMasterNodeData*); SMasterNodeData* getNodeFromWindow(CWindow*); SMasterNodeData* getMasterNodeOnWorkspace(const int&); SMasterWorkspaceData* getMasterWorkspaceData(const int&); From 49fdffacea92bc99391da0a9347b34c27d1b4525 Mon Sep 17 00:00:00 2001 From: pastalian <28638872+pastalian@users.noreply.github.com> Date: Sat, 4 Nov 2023 00:47:20 +0900 Subject: [PATCH 158/513] renderer: fix legacy_renderer build (#3732) In GLES2, `GL_RGB10_A2` and `GL_UNSIGNED_INT_2_10_10_10_REV` are defined as `GL_RGB10_A2_EXT` and `GL_UNSIGNED_INT_2_10_10_10_REV_EXT` respectively. --- src/helpers/MiscFunctions.cpp | 7 ++++++- src/render/Framebuffer.cpp | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index acb9cf20..b65f4a87 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -757,7 +757,12 @@ uint32_t drmFormatToGL(uint32_t drm) { case DRM_FORMAT_XRGB8888: case DRM_FORMAT_XBGR8888: return GL_RGBA; // doesn't matter, opengl is gucci in this case. case DRM_FORMAT_XRGB2101010: - case DRM_FORMAT_XBGR2101010: return GL_RGB10_A2; + case DRM_FORMAT_XBGR2101010: +#ifdef GLES2 + return GL_RGB10_A2_EXT; +#else + return GL_RGB10_A2; +#endif default: return GL_RGBA; } UNREACHABLE(); diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp index e1f815ce..1ebbc585 100644 --- a/src/render/Framebuffer.cpp +++ b/src/render/Framebuffer.cpp @@ -6,7 +6,13 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { RASSERT((w > 1 && h > 1), "cannot alloc a FB with negative / zero size! (attempted {}x{})", w, h); uint32_t glFormat = drmFormatToGL(drmFormat); - uint32_t glType = glFormat != GL_RGBA ? GL_UNSIGNED_INT_2_10_10_10_REV : GL_UNSIGNED_BYTE; + uint32_t glType = glFormat != GL_RGBA ? +#ifdef GLES2 + GL_UNSIGNED_INT_2_10_10_10_REV_EXT : +#else + GL_UNSIGNED_INT_2_10_10_10_REV : +#endif + GL_UNSIGNED_BYTE; if (m_iFb == (uint32_t)-1) { firstAlloc = true; From 93a2ac9de402830d301bdecdbf7aca52f88bd801 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 3 Nov 2023 15:51:33 +0000 Subject: [PATCH 159/513] fractional-scale: post error on taken fs objects fixes #3735 --- src/protocols/FractionalScale.cpp | 14 +++++++++++++- src/protocols/FractionalScale.hpp | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/protocols/FractionalScale.cpp b/src/protocols/FractionalScale.cpp index f659a63a..19e60295 100644 --- a/src/protocols/FractionalScale.cpp +++ b/src/protocols/FractionalScale.cpp @@ -76,7 +76,13 @@ static void handleAddonDestroy(wl_resource* resource) { void CFractionalScaleProtocolManager::getFractionalScale(wl_client* client, wl_resource* resource, uint32_t id, wl_resource* surface) { const auto PSURFACE = wlr_surface_from_resource(surface); - const auto PADDON = getAddonForSurface(PSURFACE); + + if (addonExists(PSURFACE)) { + wl_resource_post_error(resource, WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_FRACTIONAL_SCALE_EXISTS, "Fractional scale exists."); + return; + } + + const auto PADDON = getAddonForSurface(PSURFACE); PADDON->pResource = wl_resource_create(client, &wp_fractional_scale_v1_interface, wl_resource_get_version(resource), id); wl_resource_set_implementation(PADDON->pResource, &fractionalScaleAddonImpl, PADDON, handleAddonDestroy); @@ -84,6 +90,12 @@ void CFractionalScaleProtocolManager::getFractionalScale(wl_client* client, wl_r wp_fractional_scale_v1_send_preferred_scale(PADDON->pResource, (uint32_t)std::round(PADDON->preferredScale * 120.0)); } +bool CFractionalScaleProtocolManager::addonExists(wlr_surface* surface) { + const auto IT = std::find_if(m_vFractionalScaleAddons.begin(), m_vFractionalScaleAddons.end(), [&](const auto& other) { return other->pSurface == surface; }); + + return IT != m_vFractionalScaleAddons.end(); +} + SFractionalScaleAddon* CFractionalScaleProtocolManager::getAddonForSurface(wlr_surface* surface) { const auto IT = std::find_if(m_vFractionalScaleAddons.begin(), m_vFractionalScaleAddons.end(), [&](const auto& other) { return other->pSurface == surface; }); diff --git a/src/protocols/FractionalScale.hpp b/src/protocols/FractionalScale.hpp index 71b2c858..99696319 100644 --- a/src/protocols/FractionalScale.hpp +++ b/src/protocols/FractionalScale.hpp @@ -30,6 +30,7 @@ class CFractionalScaleProtocolManager { private: SFractionalScaleAddon* getAddonForSurface(wlr_surface*); + bool addonExists(wlr_surface*); std::vector> m_vFractionalScaleAddons; From ed3d5053b23d2b725cda507cb5fcc9e9a2f35ba9 Mon Sep 17 00:00:00 2001 From: thejch <66577496+thejch@users.noreply.github.com> Date: Fri, 3 Nov 2023 10:02:59 -0700 Subject: [PATCH 160/513] Master: fix drop_at_cursor when there are only two windows (#3734) * make drop_at_cursor work when dragging into a one-window workspace * fix drop_at_cursor when new_is_master is enabled --- src/layout/MasterLayout.cpp | 77 ++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index be8da75e..8cc35ee6 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -133,34 +133,67 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc const auto PWORKSPACEDATA = getMasterWorkspaceData(pWindow->m_iWorkspaceID); eOrientation orientation = PWORKSPACEDATA->orientation; const auto NODEIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *PNODE); + + bool forceDropAsMaster = false; + // if dragging window to move, drop it at the cursor position instead of bottom/top of stack if (*PDROPATCURSOR && g_pInputManager->dragMode == MBIND_MOVE) { - // if dragging window to move, drop it at the cursor position instead of bottom/top of stack - for (auto it = m_lMasterNodesData.begin(); it != m_lMasterNodesData.end(); ++it) { - if (it->workspaceID != pWindow->m_iWorkspaceID) - continue; - const wlr_box box = it->pWindow->getWindowIdealBoundingBoxIgnoreReserved(); - if (wlr_box_contains_point(&box, MOUSECOORDS.x, MOUSECOORDS.y)) { // TODO: Deny when not using mouse - switch (orientation) { - case ORIENTATION_LEFT: - case ORIENTATION_RIGHT: - if (MOUSECOORDS.y > it->pWindow->middle().y) - ++it; - break; - case ORIENTATION_TOP: - case ORIENTATION_BOTTOM: - if (MOUSECOORDS.x > it->pWindow->middle().x) - ++it; - break; - case ORIENTATION_CENTER: break; - default: UNREACHABLE(); + if (WINDOWSONWORKSPACE > 2) { + for (auto it = m_lMasterNodesData.begin(); it != m_lMasterNodesData.end(); ++it) { + if (it->workspaceID != pWindow->m_iWorkspaceID) + continue; + const wlr_box box = it->pWindow->getWindowIdealBoundingBoxIgnoreReserved(); + if (wlr_box_contains_point(&box, MOUSECOORDS.x, MOUSECOORDS.y)) { + switch (orientation) { + case ORIENTATION_LEFT: + case ORIENTATION_RIGHT: + if (MOUSECOORDS.y > it->pWindow->middle().y) + ++it; + break; + case ORIENTATION_TOP: + case ORIENTATION_BOTTOM: + if (MOUSECOORDS.x > it->pWindow->middle().x) + ++it; + break; + case ORIENTATION_CENTER: break; + default: UNREACHABLE(); + } + m_lMasterNodesData.splice(it, m_lMasterNodesData, NODEIT); + break; + } + } + } else if (WINDOWSONWORKSPACE == 2) { + // when dropping as the second tiled window in the workspace, + // make it the master only if the cursor is on the master side of the screen + for (auto& nd : m_lMasterNodesData) { + if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) { + switch (orientation) { + case ORIENTATION_LEFT: + case ORIENTATION_CENTER: + if (MOUSECOORDS.x < nd.pWindow->middle().x) + forceDropAsMaster = true; + break; + case ORIENTATION_RIGHT: + if (MOUSECOORDS.x > nd.pWindow->middle().x) + forceDropAsMaster = true; + break; + case ORIENTATION_TOP: + if (MOUSECOORDS.y < nd.pWindow->middle().y) + forceDropAsMaster = true; + break; + case ORIENTATION_BOTTOM: + if (MOUSECOORDS.y > nd.pWindow->middle().y) + forceDropAsMaster = true; + break; + default: UNREACHABLE(); + } + break; } - m_lMasterNodesData.splice(it, m_lMasterNodesData, NODEIT); - break; } } } - if (*PNEWISMASTER || WINDOWSONWORKSPACE == 1 || (!pWindow->m_bFirstMap && OPENINGON->isMaster)) { + if ((*PNEWISMASTER && g_pInputManager->dragMode != MBIND_MOVE) || WINDOWSONWORKSPACE == 1 || (WINDOWSONWORKSPACE > 2 && !pWindow->m_bFirstMap && OPENINGON->isMaster) || + forceDropAsMaster) { for (auto& nd : m_lMasterNodesData) { if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) { nd.isMaster = false; From 9d2a5fb41752c0dcc8e863d7e98b541656584dd9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 3 Nov 2023 19:07:11 +0000 Subject: [PATCH 161/513] renderer: improvements to wayland surface small() detection --- src/helpers/WLSurface.cpp | 2 +- src/render/Renderer.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/helpers/WLSurface.cpp b/src/helpers/WLSurface.cpp index ffd764a1..33109b94 100644 --- a/src/helpers/WLSurface.cpp +++ b/src/helpers/WLSurface.cpp @@ -31,7 +31,7 @@ bool CWLSurface::small() const { if (!m_pOwner || !exists()) return false; - return m_pOwner->m_vReportedSize.x > m_pWLRSurface->current.buffer_width || m_pOwner->m_vReportedSize.y > m_pWLRSurface->current.buffer_height; + return std::abs(m_pOwner->m_vReportedSize.x - m_pWLRSurface->current.buffer_width) > 1 || std::abs(m_pOwner->m_vReportedSize.y - m_pWLRSurface->current.buffer_height) > 1; } Vector2D CWLSurface::correctSmallVec() const { diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 72ad3db7..79aabc6e 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -341,6 +341,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* const auto REALPOS = pWindow->m_vRealPosition.vec() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset.vec()); static auto* const PDIMAROUND = &g_pConfigManager->getConfigValuePtr("decoration:dim_around")->floatValue; static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; + static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue; SRenderData renderdata = {pMonitor, time, REALPOS.x, REALPOS.y}; if (ignorePosition) { @@ -432,7 +433,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* if ((pWindow->m_bIsX11 && *PXWLUSENN) || pWindow->m_sAdditionalConfigData.nearestNeighbor.toUnderlying()) g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; - if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall && renderdata.blur) { + if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall && renderdata.blur && *PBLUR) { wlr_box wb = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h}; scaleBox(&wb, pMonitor->scale); g_pHyprOpenGL->renderRectWithBlur(&wb, CColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1); From 21ba8b363e94294c3af8ac535728d5ad27762d35 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 3 Nov 2023 21:02:12 +0000 Subject: [PATCH 162/513] fractional-scale: fix addon existence check --- src/protocols/FractionalScale.cpp | 11 ++--------- src/protocols/FractionalScale.hpp | 1 - 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/protocols/FractionalScale.cpp b/src/protocols/FractionalScale.cpp index 19e60295..f284dd0d 100644 --- a/src/protocols/FractionalScale.cpp +++ b/src/protocols/FractionalScale.cpp @@ -76,26 +76,19 @@ static void handleAddonDestroy(wl_resource* resource) { void CFractionalScaleProtocolManager::getFractionalScale(wl_client* client, wl_resource* resource, uint32_t id, wl_resource* surface) { const auto PSURFACE = wlr_surface_from_resource(surface); + const auto PADDON = getAddonForSurface(PSURFACE); - if (addonExists(PSURFACE)) { + if (PADDON->pResource) { wl_resource_post_error(resource, WP_FRACTIONAL_SCALE_MANAGER_V1_ERROR_FRACTIONAL_SCALE_EXISTS, "Fractional scale exists."); return; } - const auto PADDON = getAddonForSurface(PSURFACE); - PADDON->pResource = wl_resource_create(client, &wp_fractional_scale_v1_interface, wl_resource_get_version(resource), id); wl_resource_set_implementation(PADDON->pResource, &fractionalScaleAddonImpl, PADDON, handleAddonDestroy); wp_fractional_scale_v1_send_preferred_scale(PADDON->pResource, (uint32_t)std::round(PADDON->preferredScale * 120.0)); } -bool CFractionalScaleProtocolManager::addonExists(wlr_surface* surface) { - const auto IT = std::find_if(m_vFractionalScaleAddons.begin(), m_vFractionalScaleAddons.end(), [&](const auto& other) { return other->pSurface == surface; }); - - return IT != m_vFractionalScaleAddons.end(); -} - SFractionalScaleAddon* CFractionalScaleProtocolManager::getAddonForSurface(wlr_surface* surface) { const auto IT = std::find_if(m_vFractionalScaleAddons.begin(), m_vFractionalScaleAddons.end(), [&](const auto& other) { return other->pSurface == surface; }); diff --git a/src/protocols/FractionalScale.hpp b/src/protocols/FractionalScale.hpp index 99696319..71b2c858 100644 --- a/src/protocols/FractionalScale.hpp +++ b/src/protocols/FractionalScale.hpp @@ -30,7 +30,6 @@ class CFractionalScaleProtocolManager { private: SFractionalScaleAddon* getAddonForSurface(wlr_surface*); - bool addonExists(wlr_surface*); std::vector> m_vFractionalScaleAddons; From 15b25d58505f98005e44de18b7f6a83dc8b18877 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 3 Nov 2023 21:58:02 +0000 Subject: [PATCH 163/513] renderer: render oversized blur with respect to fade alpha --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 79aabc6e..1b59afe8 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -436,7 +436,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall && renderdata.blur && *PBLUR) { wlr_box wb = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h}; scaleBox(&wb, pMonitor->scale); - g_pHyprOpenGL->renderRectWithBlur(&wb, CColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1); + g_pHyprOpenGL->renderRectWithBlur(&wb, CColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1, renderdata.fadeAlpha); renderdata.blur = false; } From 200cccdd3bbb3e093164d6cce61eedfe527f74da Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 3 Nov 2023 22:47:12 +0000 Subject: [PATCH 164/513] events: set reported size on the end of mapping fixes #3743 --- src/events/Windows.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index ce65fa72..19ea7dde 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -651,6 +651,9 @@ void Events::listener_mapWindow(void* owner, void* data) { if (g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal()) == g_pCompositor->m_pLastWindow) g_pInputManager->simulateMouseMovement(); + + // fix some xwayland apps that don't behave nicely + PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; } void Events::listener_unmapWindow(void* owner, void* data) { From 54e51b7acf809b4cf705ae516f78a910c70e651f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 4 Nov 2023 13:09:33 +0000 Subject: [PATCH 165/513] events: better adjust to unreported sizes for xwayland apps fixes #3745 --- src/events/Windows.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 19ea7dde..59bd5fef 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -653,7 +653,8 @@ void Events::listener_mapWindow(void* owner, void* data) { g_pInputManager->simulateMouseMovement(); // fix some xwayland apps that don't behave nicely - PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; + PWINDOW->m_vPendingReportedSize = PWINDOW->m_vRealSize.goalv(); + PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; } void Events::listener_unmapWindow(void* owner, void* data) { @@ -1013,6 +1014,7 @@ void Events::listener_configureX11(void* owner, void* data) { if (!PWINDOW->m_uSurface.xwayland->surface || !PWINDOW->m_uSurface.xwayland->surface->mapped || !PWINDOW->m_bMappedX11) { wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height); + PWINDOW->m_vReportedSize = {E->width, E->height}; return; } @@ -1058,6 +1060,8 @@ void Events::listener_configureX11(void* owner, void* data) { g_pHyprRenderer->damageWindow(PWINDOW); PWINDOW->updateWindowDecos(); + + PWINDOW->m_vReportedSize = {E->width, E->height}; } void Events::listener_unmanagedSetGeometry(void* owner, void* data) { From 73e78f05ad5cafa20ac5bf177c94ac9ecca37097 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sat, 4 Nov 2023 13:10:52 +0000 Subject: [PATCH 166/513] Decos: Window decoration flags, shadow improvements (#3739) --- src/Window.cpp | 2 +- src/layout/DwindleLayout.cpp | 2 +- src/layout/MasterLayout.cpp | 2 +- src/managers/KeybindManager.cpp | 2 +- src/managers/input/InputManager.cpp | 8 +- src/render/OpenGL.cpp | 53 +++++++++--- src/render/OpenGL.hpp | 2 +- src/render/Renderer.cpp | 30 ++++++- src/render/Shader.hpp | 13 +-- .../decorations/CHyprDropShadowDecoration.cpp | 80 +++++++++++-------- .../decorations/CHyprDropShadowDecoration.hpp | 4 + .../decorations/CHyprGroupBarDecoration.cpp | 12 ++- .../decorations/CHyprGroupBarDecoration.hpp | 6 +- .../decorations/IHyprWindowDecoration.cpp | 18 +++-- .../decorations/IHyprWindowDecoration.hpp | 23 +++++- src/render/shaders/Shadow.hpp | 7 ++ src/render/shaders/Textures.hpp | 3 + 17 files changed, 192 insertions(+), 75 deletions(-) diff --git a/src/Window.cpp b/src/Window.cpp index 2f0809bf..f66a3139 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -146,7 +146,7 @@ wlr_box CWindow::getWindowInputBox() { for (auto& wd : m_dWindowDecorations) { - if (!wd->allowsInput()) + if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) continue; const auto EXTENTS = wd->getWindowDecorationExtents(); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 30568375..45db3855 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -317,7 +317,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire if (!m_vOverrideFocalPoint && g_pInputManager->m_bWasDraggingWindow) { for (auto& wd : OPENINGON->pWindow->m_dWindowDecorations) { - if (!wd->allowsInput()) + if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) continue; if (wd->getWindowDecorationRegion().containsPoint(MOUSECOORDS)) { diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 8cc35ee6..0fbb2391 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -96,7 +96,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc if (g_pInputManager->m_bWasDraggingWindow && OPENINGON) { for (auto& wd : OPENINGON->pWindow->m_dWindowDecorations) { - if (!wd->allowsInput()) + if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) continue; if (wd->getWindowDecorationRegion().containsPoint(MOUSECOORDS)) { diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 23adc165..ac995ad9 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1841,7 +1841,7 @@ void CKeybindManager::mouse(std::string args) { if (pWindow && !pWindow->m_bIsFullscreen && !pWindow->hasPopupAt(mouseCoords)) { for (auto& wd : pWindow->m_dWindowDecorations) { - if (!wd->allowsInput()) + if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) continue; if (wd->getWindowDecorationRegion().containsPoint(mouseCoords)) { diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 09571291..dcbf4e3c 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -585,7 +585,7 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { if (w && !w->m_bIsFullscreen && !w->hasPopupAt(mouseCoords)) { for (auto& wd : w->m_dWindowDecorations) { - if (!wd->allowsInput()) + if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) continue; if (wd->getWindowDecorationRegion().containsPoint(mouseCoords)) { @@ -1634,11 +1634,11 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) { bool onDeco = false; - for (auto& d : w->m_dWindowDecorations) { - if (!d->allowsInput()) + for (auto& wd : w->m_dWindowDecorations) { + if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) continue; - if (d->getWindowDecorationRegion().containsPoint(mouseCoords)) { + if (wd->getWindowDecorationRegion().containsPoint(mouseCoords)) { onDeco = true; break; } diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index d23a1d38..d8637a53 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -329,18 +329,21 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shBLURFINISH.contrast = glGetUniformLocation(prog, "contrast"); m_RenderData.pCurrentMonData->m_shBLURFINISH.brightness = glGetUniformLocation(prog, "brightness"); - prog = createProgram(QUADVERTSRC, FRAGSHADOW); - m_RenderData.pCurrentMonData->m_shSHADOW.program = prog; - m_RenderData.pCurrentMonData->m_shSHADOW.proj = glGetUniformLocation(prog, "proj"); - m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos"); - m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord"); - m_RenderData.pCurrentMonData->m_shSHADOW.topLeft = glGetUniformLocation(prog, "topLeft"); - m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight"); - m_RenderData.pCurrentMonData->m_shSHADOW.fullSize = glGetUniformLocation(prog, "fullSize"); - m_RenderData.pCurrentMonData->m_shSHADOW.radius = glGetUniformLocation(prog, "radius"); - m_RenderData.pCurrentMonData->m_shSHADOW.range = glGetUniformLocation(prog, "range"); - m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower"); - m_RenderData.pCurrentMonData->m_shSHADOW.color = glGetUniformLocation(prog, "color"); + prog = createProgram(QUADVERTSRC, FRAGSHADOW); + m_RenderData.pCurrentMonData->m_shSHADOW.program = prog; + m_RenderData.pCurrentMonData->m_shSHADOW.proj = glGetUniformLocation(prog, "proj"); + m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos"); + m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord"); + m_RenderData.pCurrentMonData->m_shSHADOW.matteTexAttrib = glGetAttribLocation(prog, "texcoordMatte"); + m_RenderData.pCurrentMonData->m_shSHADOW.alphaMatte = glGetUniformLocation(prog, "alphaMatte"); + m_RenderData.pCurrentMonData->m_shSHADOW.topLeft = glGetUniformLocation(prog, "topLeft"); + m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight"); + m_RenderData.pCurrentMonData->m_shSHADOW.fullSize = glGetUniformLocation(prog, "fullSize"); + m_RenderData.pCurrentMonData->m_shSHADOW.radius = glGetUniformLocation(prog, "radius"); + m_RenderData.pCurrentMonData->m_shSHADOW.range = glGetUniformLocation(prog, "range"); + m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower"); + m_RenderData.pCurrentMonData->m_shSHADOW.color = glGetUniformLocation(prog, "color"); + m_RenderData.pCurrentMonData->m_shSHADOW.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte"); prog = createProgram(QUADVERTSRC, FRAGBORDER1); m_RenderData.pCurrentMonData->m_shBORDER1.program = prog; @@ -1637,7 +1640,7 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) { m_bEndFrame = false; } -void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, float a) { +void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, float a, CFramebuffer* matte) { RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!"); RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!"); RASSERT(m_pCurrentWindow, "Tried to render shadow without a window!"); @@ -1657,6 +1660,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl static auto* const PSHADOWPOWER = &g_pConfigManager->getConfigValuePtr("decoration:shadow_render_power")->intValue; const auto SHADOWPOWER = std::clamp((int)*PSHADOWPOWER, 1, 4); + const auto USEMATTE = matte; const auto col = m_pCurrentWindow->m_cRealShadowColor.col(); @@ -1691,11 +1695,33 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.range, range); glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower, SHADOWPOWER); + if (USEMATTE) { + glUniform1i(m_RenderData.pCurrentMonData->m_shSHADOW.useAlphaMatte, 1); + glUniform1i(m_RenderData.pCurrentMonData->m_shSHADOW.alphaMatte, 0); + glActiveTexture(GL_TEXTURE0); + glBindTexture(matte->m_cTex.m_iTarget, matte->m_cTex.m_iTexID); + } else { + glUniform1i(m_RenderData.pCurrentMonData->m_shSHADOW.useAlphaMatte, 0); + } + + const float texVerts[] = { + ((float)(box->x + box->width) / m_RenderData.pMonitor->vecPixelSize.x), + ((float)box->y / m_RenderData.pMonitor->vecPixelSize.y), // top right + ((float)box->x / m_RenderData.pMonitor->vecPixelSize.x), + ((float)box->y / m_RenderData.pMonitor->vecPixelSize.y), // top left + ((float)(box->x + box->width) / m_RenderData.pMonitor->vecPixelSize.x), + ((float)(box->y + box->height) / m_RenderData.pMonitor->vecPixelSize.y), // bottom right + ((float)box->x / m_RenderData.pMonitor->vecPixelSize.x), + ((float)(box->y + box->height) / m_RenderData.pMonitor->vecPixelSize.y), // bottom left + }; + glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); + glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shSHADOW.matteTexAttrib, 2, GL_FLOAT, GL_FALSE, 0, texVerts); glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib); glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib); + glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.matteTexAttrib); if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) { CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height}; @@ -1714,6 +1740,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl } } + glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.matteTexAttrib); glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib); glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib); } diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 0d4b7852..ab3eb7cf 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -111,7 +111,7 @@ class CHyprOpenGLImpl { void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0, bool allowCustomUV = false); void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); - void renderRoundedShadow(wlr_box*, int round, int range, float a = 1.0); + void renderRoundedShadow(wlr_box*, int round, int range, float a = 1.0, CFramebuffer* matte = nullptr); void renderBorder(wlr_box*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); void saveMatrix(); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 1b59afe8..82175b99 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -425,9 +425,21 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* } } - if (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL) - for (auto& wd : pWindow->m_dWindowDecorations) + if (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL) { + for (auto& wd : pWindow->m_dWindowDecorations) { + if (wd->getDecorationLayer() != DECORATION_LAYER_BOTTOM) + continue; + wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, Vector2D{renderdata.x, renderdata.y} - PREOFFSETPOS); + } + + for (auto& wd : pWindow->m_dWindowDecorations) { + if (wd->getDecorationLayer() != DECORATION_LAYER_UNDER) + continue; + + wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, Vector2D{renderdata.x, renderdata.y} - PREOFFSETPOS); + } + } static auto* const PXWLUSENN = &g_pConfigManager->getConfigValuePtr("xwayland:use_nearest_neighbor")->intValue; if ((pWindow->m_bIsX11 && *PXWLUSENN) || pWindow->m_sAdditionalConfigData.nearestNeighbor.toUnderlying()) @@ -470,6 +482,13 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* } } + for (auto& wd : pWindow->m_dWindowDecorations) { + if (wd->getDecorationLayer() != DECORATION_LAYER_OVER) + continue; + + wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, Vector2D{renderdata.x, renderdata.y} - PREOFFSETPOS); + } + if (TRANSFORMERSPRESENT) { CFramebuffer* last = g_pHyprOpenGL->m_RenderData.currentFB; @@ -501,6 +520,13 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false; } + + for (auto& wd : pWindow->m_dWindowDecorations) { + if (wd->getDecorationLayer() != DECORATION_LAYER_OVERLAY) + continue; + + wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, Vector2D{renderdata.x, renderdata.y} - PREOFFSETPOS); + } } EMIT_HOOK_EVENT("render", RENDER_POST_WINDOW); diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp index e972eeb9..b67f61ef 100644 --- a/src/render/Shader.hpp +++ b/src/render/Shader.hpp @@ -10,10 +10,12 @@ class CShader { GLuint program = 0; GLint proj = -1; GLint color = -1; + GLint alphaMatte = -1; GLint tex = -1; GLint alpha = -1; GLint posAttrib = -1; GLint texAttrib = -1; + GLint matteTexAttrib = -1; GLint discardOpaque = -1; GLint discardAlpha = -1; GLfloat discardAlphaValue = -1; @@ -29,8 +31,9 @@ class CShader { GLint halfpixel = -1; - GLint range = -1; - GLint shadowPower = -1; + GLint range = -1; + GLint shadowPower = -1; + GLint useAlphaMatte = -1; // always inverted GLint applyTint = -1; GLint tint = -1; @@ -43,9 +46,9 @@ class CShader { GLint distort = -1; GLint output = -1; - GLint noise = -1; - GLint contrast = -1; - GLint brightness = -1; + GLint noise = -1; + GLint contrast = -1; + GLint brightness = -1; GLint getUniformLocation(const std::string&); diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index ee1a65a5..c2edb9ce 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -45,6 +45,32 @@ void CHyprDropShadowDecoration::updateWindow(CWindow* pWindow) { m_vLastWindowSize = pWindow->m_vRealSize.vec(); damageEntire(); + + const auto BORDER = m_pWindow->getRealBorderSize(); + + // calculate extents of decos with the DECORATION_PART_OF_MAIN_WINDOW flag + SWindowDecorationExtents maxExtents; + + for (auto& wd : m_pWindow->m_dWindowDecorations) { + // conveniently, this will also skip us. + if (!(wd->getDecorationFlags() & DECORATION_PART_OF_MAIN_WINDOW)) + continue; + + const auto EXTENTS = wd->getWindowDecorationExtents(); + + if (maxExtents.topLeft.x < EXTENTS.topLeft.x) + maxExtents.topLeft.x = EXTENTS.topLeft.x; + if (maxExtents.topLeft.y < EXTENTS.topLeft.y) + maxExtents.topLeft.y = EXTENTS.topLeft.y; + if (maxExtents.bottomRight.x < EXTENTS.bottomRight.x) + maxExtents.bottomRight.x = EXTENTS.bottomRight.x; + if (maxExtents.bottomRight.y < EXTENTS.bottomRight.y) + maxExtents.bottomRight.y = EXTENTS.bottomRight.y; + } + + m_bLastWindowBox = {(int)(m_vLastWindowPos.x - maxExtents.topLeft.x - BORDER), (int)(m_vLastWindowPos.y - maxExtents.topLeft.y - BORDER), + (int)(m_vLastWindowSize.x + maxExtents.topLeft.x + maxExtents.bottomRight.x + 2 * BORDER), + (int)(m_vLastWindowSize.y + maxExtents.topLeft.y + maxExtents.bottomRight.y + 2 * BORDER)}; } } @@ -67,7 +93,6 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D static auto* const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue; static auto* const PSHADOWSIZE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_range")->intValue; - static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue; static auto* const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue; static auto* const PSHADOWSCALE = &g_pConfigManager->getConfigValuePtr("decoration:shadow_scale")->floatValue; static auto* const PSHADOWOFFSET = &g_pConfigManager->getConfigValuePtr("decoration:shadow_offset")->vecValue; @@ -75,12 +100,11 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D if (*PSHADOWS != 1) return; // disabled - const auto ROUNDING = !m_pWindow->m_sSpecialRenderData.rounding ? - 0 : - (m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? *PROUNDING : m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying()); + const auto ROUNDING = m_pWindow->rounding() + m_pWindow->getRealBorderSize(); // draw the shadow - wlr_box fullBox = {m_vLastWindowPos.x - *PSHADOWSIZE, m_vLastWindowPos.y - *PSHADOWSIZE, m_vLastWindowSize.x + 2.0 * *PSHADOWSIZE, m_vLastWindowSize.y + 2.0 * *PSHADOWSIZE}; + wlr_box fullBox = {m_bLastWindowBox.x - *PSHADOWSIZE, m_bLastWindowBox.y - *PSHADOWSIZE, m_bLastWindowBox.width + 2.0 * *PSHADOWSIZE, + m_bLastWindowBox.height + 2.0 * *PSHADOWSIZE}; fullBox.x -= pMonitor->vecPosition.x; fullBox.y -= pMonitor->vecPosition.y; @@ -95,17 +119,17 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D if (PSHADOWOFFSET->x < 0) { fullBox.x += PSHADOWOFFSET->x; } else if (PSHADOWOFFSET->x > 0) { - fullBox.x = m_vLastWindowPos.x + m_vLastWindowSize.x - fullBox.width + (SHADOWSCALE * *PSHADOWSIZE) + PSHADOWOFFSET->x - pMonitor->vecPosition.x; + fullBox.x = m_bLastWindowBox.x + m_bLastWindowBox.width - fullBox.width + (SHADOWSCALE * *PSHADOWSIZE) + PSHADOWOFFSET->x - pMonitor->vecPosition.x; } else { - fullBox.x += ((m_vLastWindowSize.x + 2.0 * *PSHADOWSIZE) - NEWSIZE.x) / 2.0; + fullBox.x += ((m_bLastWindowBox.width + 2.0 * *PSHADOWSIZE) - NEWSIZE.x) / 2.0; } if (PSHADOWOFFSET->y < 0) { fullBox.y += PSHADOWOFFSET->y; } else if (PSHADOWOFFSET->y > 0) { - fullBox.y = m_vLastWindowPos.y + m_vLastWindowSize.y - fullBox.height + (SHADOWSCALE * *PSHADOWSIZE) + PSHADOWOFFSET->y - pMonitor->vecPosition.y; + fullBox.y = m_bLastWindowBox.y + m_bLastWindowBox.height - fullBox.height + (SHADOWSCALE * *PSHADOWSIZE) + PSHADOWOFFSET->y - pMonitor->vecPosition.y; } else { - fullBox.y += ((m_vLastWindowSize.y + 2.0 * *PSHADOWSIZE) - NEWSIZE.y) / 2.0; + fullBox.y += ((m_bLastWindowBox.height + 2.0 * *PSHADOWSIZE) - NEWSIZE.y) / 2.0; } m_seExtents = {{m_vLastWindowPos.x - fullBox.x - pMonitor->vecPosition.x + 2, m_vLastWindowPos.y - fullBox.y - pMonitor->vecPosition.y + 2}, @@ -120,39 +144,31 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D g_pHyprOpenGL->scissor((wlr_box*)nullptr); + // we'll take the liberty of using this as it should not be used rn + CFramebuffer& alphaFB = g_pHyprOpenGL->m_RenderData.pCurrentMonData->mirrorFB; + auto* LASTFB = g_pHyprOpenGL->m_RenderData.currentFB; + if (*PSHADOWIGNOREWINDOW) { - glEnable(GL_STENCIL_TEST); - - glClearStencil(0); - glClear(GL_STENCIL_BUFFER_BIT); - - glStencilFunc(GL_ALWAYS, 1, -1); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - - wlr_box windowBox = {m_vLastWindowPos.x - pMonitor->vecPosition.x, m_vLastWindowPos.y - pMonitor->vecPosition.y, m_vLastWindowSize.x, m_vLastWindowSize.y}; + wlr_box windowBox = {m_bLastWindowBox.x - pMonitor->vecPosition.x, m_bLastWindowBox.y - pMonitor->vecPosition.y, m_bLastWindowBox.width, m_bLastWindowBox.height}; scaleBox(&windowBox, pMonitor->scale); if (windowBox.width < 1 || windowBox.height < 1) { - glClearStencil(0); - glClear(GL_STENCIL_BUFFER_BIT); - glDisable(GL_STENCIL_TEST); return; // prevent assert failed } - g_pHyprOpenGL->renderRect(&windowBox, CColor(0, 0, 0, 0), ROUNDING * pMonitor->scale); + alphaFB.bind(); + g_pHyprOpenGL->clear(CColor(0, 0, 0, 0)); - glStencilFunc(GL_NOTEQUAL, 1, -1); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + g_pHyprOpenGL->renderRect(&windowBox, CColor(1.0, 1.0, 1.0, 1.0), ROUNDING * pMonitor->scale); + + LASTFB->bind(); } scaleBox(&fullBox, pMonitor->scale); - g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a); - - if (*PSHADOWIGNOREWINDOW) { - // cleanup - glClearStencil(0); - glClear(GL_STENCIL_BUFFER_BIT); - glDisable(GL_STENCIL_TEST); - } + g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a, &alphaFB); } + +eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() { + return DECORATION_LAYER_BOTTOM; +} \ No newline at end of file diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index 3a7ffb2b..7fadf851 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -17,6 +17,8 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { virtual void damageEntire(); + virtual eDecorationLayer getDecorationLayer(); + private: SWindowDecorationExtents m_seExtents; @@ -24,4 +26,6 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { Vector2D m_vLastWindowPos; Vector2D m_vLastWindowSize; + + wlr_box m_bLastWindowBox = {0}; }; \ No newline at end of file diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 3e3075ea..a34a47b7 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -301,10 +301,6 @@ void CHyprGroupBarDecoration::refreshGradients() { renderGradientTo(m_tGradientInactive, ((CGradientValueData*)PCOLINACTIVE->get())->m_vColors[0]); } -bool CHyprGroupBarDecoration::allowsInput() { - return true; -} - bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D& pos) { if (!pDraggedWindow->canBeGroupedInto(m_pWindow)) @@ -407,3 +403,11 @@ void CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) { if (!g_pCompositor->isWindowActive(pWindow)) g_pCompositor->focusWindow(pWindow); } + +eDecorationLayer CHyprGroupBarDecoration::getDecorationLayer() { + return DECORATION_LAYER_OVER; +} + +uint64_t CHyprGroupBarDecoration::getDecorationFlags() { + return DECORATION_ALLOWS_MOUSE_INPUT; +} \ No newline at end of file diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp index 05736d4b..569fda21 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.hpp +++ b/src/render/decorations/CHyprGroupBarDecoration.hpp @@ -33,14 +33,16 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { virtual SWindowDecorationExtents getWindowDecorationReservedArea(); - virtual bool allowsInput(); - virtual void onBeginWindowDragOnDeco(const Vector2D&); virtual bool onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D&); virtual void onMouseButtonOnDeco(const Vector2D&, wlr_pointer_button_event*); + virtual eDecorationLayer getDecorationLayer(); + + virtual uint64_t getDecorationFlags(); + private: SWindowDecorationExtents m_seExtents; diff --git a/src/render/decorations/IHyprWindowDecoration.cpp b/src/render/decorations/IHyprWindowDecoration.cpp index e0868b0b..d2b9b0f9 100644 --- a/src/render/decorations/IHyprWindowDecoration.cpp +++ b/src/render/decorations/IHyprWindowDecoration.cpp @@ -25,14 +25,22 @@ CRegion IHyprWindowDecoration::getWindowDecorationRegion() { m_pWindow->m_vRealSize.vec().y + 2 * BORDERSIZE)); } -bool IHyprWindowDecoration::allowsInput() { - return false; +void IHyprWindowDecoration::onBeginWindowDragOnDeco(const Vector2D&) { + ; } -void IHyprWindowDecoration::onBeginWindowDragOnDeco(const Vector2D&) {} - bool IHyprWindowDecoration::onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D&) { return true; } -void IHyprWindowDecoration::onMouseButtonOnDeco(const Vector2D&, wlr_pointer_button_event*) {} +void IHyprWindowDecoration::onMouseButtonOnDeco(const Vector2D&, wlr_pointer_button_event*) { + ; +} + +eDecorationLayer IHyprWindowDecoration::getDecorationLayer() { + return DECORATION_LAYER_UNDER; +} + +uint64_t IHyprWindowDecoration::getDecorationFlags() { + return 0; +} \ No newline at end of file diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp index eadc486f..29d50595 100644 --- a/src/render/decorations/IHyprWindowDecoration.hpp +++ b/src/render/decorations/IHyprWindowDecoration.hpp @@ -3,7 +3,8 @@ #include "../../defines.hpp" #include "../../helpers/Region.hpp" -enum eDecorationType { +enum eDecorationType +{ DECORATION_NONE = -1, DECORATION_GROUPBAR, DECORATION_SHADOW, @@ -15,6 +16,20 @@ struct SWindowDecorationExtents { Vector2D bottomRight; }; +enum eDecorationLayer +{ + DECORATION_LAYER_BOTTOM = 0, /* lowest. */ + DECORATION_LAYER_UNDER, /* under the window, but above BOTTOM */ + DECORATION_LAYER_OVER, /* above the window, but below its popups */ + DECORATION_LAYER_OVERLAY /* above everything of the window, including popups */ +}; + +enum eDecorationFlags +{ + DECORATION_ALLOWS_MOUSE_INPUT = 1 << 0, /* this decoration accepts mouse input */ + DECORATION_PART_OF_MAIN_WINDOW = 1 << 1, /* this decoration is a *seamless* part of the main window, so stuff like shadows will include it */ +}; + class CWindow; class CMonitor; @@ -37,14 +52,16 @@ class IHyprWindowDecoration { virtual CRegion getWindowDecorationRegion(); - virtual bool allowsInput(); - virtual void onBeginWindowDragOnDeco(const Vector2D&); // called when the user calls the "movewindow" mouse dispatcher on the deco virtual bool onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D&); // returns true if the window should be placed by the layout virtual void onMouseButtonOnDeco(const Vector2D&, wlr_pointer_button_event*); + virtual eDecorationLayer getDecorationLayer(); + + virtual uint64_t getDecorationFlags(); + private: CWindow* m_pWindow = nullptr; }; diff --git a/src/render/shaders/Shadow.hpp b/src/render/shaders/Shadow.hpp index 2c7b07b2..f9bdeb8d 100644 --- a/src/render/shaders/Shadow.hpp +++ b/src/render/shaders/Shadow.hpp @@ -5,7 +5,9 @@ inline const std::string FRAGSHADOW = R"#( precision mediump float; varying vec4 v_color; +uniform sampler2D alphaMatte; varying vec2 v_texcoord; +varying vec2 v_texcoordMatte; uniform vec2 topLeft; uniform vec2 bottomRight; @@ -13,6 +15,7 @@ uniform vec2 fullSize; uniform float radius; uniform float range; uniform float shadowPower; +uniform int useAlphaMatte; float pixAlphaRoundedDistance(float distanceToCorner) { if (distanceToCorner > radius) { @@ -74,6 +77,10 @@ void main() { } } + if (useAlphaMatte == 1) { + pixColor[3] *= 1.0 - texture2D(alphaMatte, v_texcoordMatte)[3]; + } + if (pixColor[3] == 0.0) { discard; return; } diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index 109840ca..6f19ac9f 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -37,13 +37,16 @@ uniform mat3 proj; uniform vec4 color; attribute vec2 pos; attribute vec2 texcoord; +attribute vec2 texcoordMatte; varying vec4 v_color; varying vec2 v_texcoord; +varying vec2 v_texcoordMatte; void main() { gl_Position = vec4(proj * vec3(pos, 1.0), 1.0); v_color = color; v_texcoord = texcoord; + v_texcoordMatte = texcoordMatte; })#"; inline const std::string QUADFRAGSRC = R"#( From 55b4f84fea33adee3ec4b0a69c2bca6e7a1f5754 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sat, 4 Nov 2023 17:03:05 +0000 Subject: [PATCH 167/513] Internal: Hyprland box implementation (#3755) * box impl * remove unused operators * missed applyfromwlr --- example/examplePlugin/customDecoration.cpp | 12 +- src/Compositor.cpp | 96 ++++++------ src/SharedDefs.hpp | 14 ++ src/Window.cpp | 30 ++-- src/Window.hpp | 14 +- src/debug/HyprDebugOverlay.cpp | 2 +- src/debug/HyprDebugOverlay.hpp | 2 +- src/debug/HyprNotificationOverlay.cpp | 8 +- src/debug/HyprNotificationOverlay.hpp | 4 +- src/events/Layers.cpp | 14 +- src/events/Monitors.cpp | 5 +- src/events/Popups.cpp | 30 ++-- src/events/Windows.cpp | 2 +- src/helpers/Box.cpp | 104 +++++++++++++ src/helpers/Box.hpp | 66 +++++++++ src/helpers/MiscFunctions.cpp | 7 - src/helpers/MiscFunctions.hpp | 1 - src/helpers/Monitor.cpp | 4 +- src/helpers/Monitor.hpp | 2 +- src/helpers/Region.cpp | 6 +- src/helpers/Region.hpp | 6 +- src/helpers/SubsurfaceTree.cpp | 7 +- src/helpers/Vector2D.hpp | 3 + src/helpers/WLClasses.hpp | 6 +- src/hyprerror/HyprError.cpp | 2 +- src/hyprerror/HyprError.hpp | 2 +- src/includes.hpp | 1 + src/layout/IHyprLayout.cpp | 4 +- src/layout/MasterLayout.cpp | 4 +- src/managers/AnimationManager.cpp | 9 +- src/managers/XWaylandManager.cpp | 8 +- src/managers/XWaylandManager.hpp | 2 +- src/managers/input/InputManager.cpp | 26 ++-- src/managers/input/InputMethodRelay.cpp | 6 +- src/protocols/Screencopy.cpp | 5 +- src/protocols/Screencopy.hpp | 4 +- src/protocols/TextInputV1.cpp | 2 +- src/protocols/TextInputV1.hpp | 4 +- src/protocols/ToplevelExport.cpp | 8 +- src/render/OpenGL.cpp | 139 ++++++++---------- src/render/OpenGL.hpp | 26 ++-- src/render/Renderer.cpp | 97 ++++++------ src/render/Renderer.hpp | 6 +- .../decorations/CHyprDropShadowDecoration.cpp | 54 +++---- .../decorations/CHyprDropShadowDecoration.hpp | 3 +- .../decorations/CHyprGroupBarDecoration.cpp | 10 +- .../decorations/IHyprWindowDecoration.hpp | 5 - 47 files changed, 520 insertions(+), 352 deletions(-) create mode 100644 src/helpers/Box.cpp create mode 100644 src/helpers/Box.hpp diff --git a/example/examplePlugin/customDecoration.cpp b/example/examplePlugin/customDecoration.cpp index 52b8b715..e2b5d136 100644 --- a/example/examplePlugin/customDecoration.cpp +++ b/example/examplePlugin/customDecoration.cpp @@ -33,8 +33,8 @@ void CCustomDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& offset (m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? *PROUNDING : m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying()); // draw the border - wlr_box fullBox = {(int)(m_vLastWindowPos.x - *PBORDERSIZE), (int)(m_vLastWindowPos.y - *PBORDERSIZE), (int)(m_vLastWindowSize.x + 2.0 * *PBORDERSIZE), - (int)(m_vLastWindowSize.y + 2.0 * *PBORDERSIZE)}; + CBox fullBox = {(int)(m_vLastWindowPos.x - *PBORDERSIZE), (int)(m_vLastWindowPos.y - *PBORDERSIZE), (int)(m_vLastWindowSize.x + 2.0 * *PBORDERSIZE), + (int)(m_vLastWindowSize.y + 2.0 * *PBORDERSIZE)}; fullBox.x -= pMonitor->vecPosition.x; fullBox.y -= pMonitor->vecPosition.y; @@ -49,9 +49,9 @@ void CCustomDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& offset if (fullBox.width < 1 || fullBox.height < 1) return; // don't draw invisible shadows - g_pHyprOpenGL->scissor((wlr_box*)nullptr); + g_pHyprOpenGL->scissor((CBox*)nullptr); - scaleBox(&fullBox, pMonitor->scale); + fullBox.scale(pMonitor->scale); g_pHyprOpenGL->renderBorder(&fullBox, CColor(*PCOLOR), *PROUNDING * pMonitor->scale + *PBORDERSIZE * 2, a); } @@ -68,7 +68,7 @@ void CCustomDecoration::updateWindow(CWindow* pWindow) { } void CCustomDecoration::damageEntire() { - wlr_box dm = {(int)(m_vLastWindowPos.x - m_seExtents.topLeft.x), (int)(m_vLastWindowPos.y - m_seExtents.topLeft.y), - (int)(m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x), (int)m_seExtents.topLeft.y}; + CBox dm = {(int)(m_vLastWindowPos.x - m_seExtents.topLeft.x), (int)(m_vLastWindowPos.y - m_seExtents.topLeft.y), + (int)(m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x), (int)m_seExtents.topLeft.y}; g_pHyprRenderer->damageBox(&dm); } \ No newline at end of file diff --git a/src/Compositor.cpp b/src/Compositor.cpp index f8d61501..53cd2e83 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -631,38 +631,35 @@ CWindow* CCompositor::vectorToWindow(const Vector2D& pos) { if (PMONITOR->specialWorkspaceID) { for (auto& w : m_vWindows | std::views::reverse) { - wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; - if (w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->isHidden() && - !w->m_bNoFocus) + auto box = w->getWindowMainSurfaceBox(); + if (w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && box.containsPoint(pos) && !w->isHidden() && !w->m_bNoFocus) return w.get(); } for (auto& w : m_vWindows) { - wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; - if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && !w->m_bIsFloating && !w->isHidden() && - !w->m_bNoFocus) + auto box = w->getWindowMainSurfaceBox(); + if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && box.containsPoint(pos) && w->m_bIsMapped && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus) return w.get(); } } // pinned for (auto& w : m_vWindows | std::views::reverse) { - wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; - if (wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && w->m_bIsFloating && !w->isHidden() && w->m_bPinned && !w->m_bNoFocus) + auto box = w->getWindowMainSurfaceBox(); + if (box.containsPoint(pos) && w->m_bIsMapped && w->m_bIsFloating && !w->isHidden() && w->m_bPinned && !w->m_bNoFocus) return w.get(); } // first loop over floating cuz they're above, m_vWindows should be sorted bottom->top, for tiled it doesn't matter. for (auto& w : m_vWindows | std::views::reverse) { - wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; - if (wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && - !w->m_bNoFocus) + auto box = w->getWindowMainSurfaceBox(); + if (box.containsPoint(pos) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_bNoFocus) return w.get(); } for (auto& w : m_vWindows) { - wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; - if (wlr_box_contains_point(&box, pos.x, pos.y) && w->m_bIsMapped && !w->m_bIsFloating && PMONITOR->activeWorkspace == w->m_iWorkspaceID && !w->isHidden() && !w->m_bNoFocus) + auto box = w->getWindowMainSurfaceBox(); + if (box.containsPoint(pos) && w->m_bIsMapped && !w->m_bIsFloating && PMONITOR->activeWorkspace == w->m_iWorkspaceID && !w->isHidden() && !w->m_bNoFocus) return w.get(); } @@ -674,15 +671,15 @@ CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) { if (PMONITOR->specialWorkspaceID) { for (auto& w : m_vWindows) { - wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; - if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && wlr_box_contains_point(&box, pos.x, pos.y) && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus) + CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; + if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && box.containsPoint(pos) && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus) return w.get(); } } for (auto& w : m_vWindows) { - wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; - if (w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus) + CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; + if (w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus) return w.get(); } @@ -700,16 +697,16 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { if (PMONITOR->specialWorkspaceID) { for (auto& w : m_vWindows | std::views::reverse) { const auto BB = w->getWindowInputBox(); - wlr_box box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA}; - if (w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->isHidden() && - !w->m_bX11ShouldntFocus && !w->m_bNoFocus) + CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA}; + if (w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && box.containsPoint(pos) && !w->isHidden() && !w->m_bX11ShouldntFocus && + !w->m_bNoFocus) return w.get(); } for (auto& w : m_vWindows) { - wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; - if (!w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && !w->isHidden() && - !w->m_bX11ShouldntFocus && !w->m_bNoFocus) + CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; + if (!w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && box.containsPoint(pos) && !w->isHidden() && !w->m_bX11ShouldntFocus && + !w->m_bNoFocus) return w.get(); } } @@ -717,9 +714,9 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { // pinned windows on top of floating regardless for (auto& w : m_vWindows | std::views::reverse) { const auto BB = w->getWindowInputBox(); - wlr_box box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA}; + CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA}; if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_bNoFocus) { - if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y)) + if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y})) return w.get(); if (!w->m_bIsX11) { @@ -732,13 +729,13 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { // first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter. for (auto& w : m_vWindows | std::views::reverse) { const auto BB = w->getWindowInputBox(); - wlr_box box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA}; + CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA}; if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_bNoFocus) { // OR windows should add focus to parent if (w->m_bX11ShouldntFocus && w->m_iX11Type != 2) continue; - if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y)) { + if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y})) { if (w->m_bIsX11 && w->m_iX11Type == 2 && !wlr_xwayland_or_surface_wants_focus(w->m_uSurface.xwayland)) { // Override Redirect @@ -764,9 +761,9 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { } } for (auto& w : m_vWindows) { - wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; - if (!w->m_bIsFloating && w->m_bIsMapped && wlr_box_contains_point(&box, pos.x, pos.y) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->isHidden() && - !w->m_bX11ShouldntFocus && !w->m_bNoFocus) + CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; + if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->isHidden() && !w->m_bX11ShouldntFocus && + !w->m_bNoFocus) return w.get(); } @@ -778,37 +775,36 @@ CWindow* CCompositor::windowFromCursor() { if (PMONITOR->specialWorkspaceID) { for (auto& w : m_vWindows | std::views::reverse) { - wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; - if (w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && + CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; + if (w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && !w->isHidden() && !w->m_bNoFocus) return w.get(); } for (auto& w : m_vWindows) { - wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; - if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && !w->m_bNoFocus) + CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; + if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && !w->m_bNoFocus) return w.get(); } } // pinned for (auto& w : m_vWindows | std::views::reverse) { - wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; - if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && w->m_bIsFloating && w->m_bPinned && !w->m_bNoFocus) + CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; + if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && w->m_bPinned && !w->m_bNoFocus) return w.get(); } // first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter. for (auto& w : m_vWindows | std::views::reverse) { - wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; - if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bPinned && - !w->m_bNoFocus) + CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; + if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->m_bPinned && !w->m_bNoFocus) return w.get(); } for (auto& w : m_vWindows) { - wlr_box box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; - if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bNoFocus) + CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; + if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->m_bNoFocus) return w.get(); } @@ -817,14 +813,14 @@ CWindow* CCompositor::windowFromCursor() { CWindow* CCompositor::windowFloatingFromCursor() { for (auto& w : m_vWindows | std::views::reverse) { - wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; - if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && w->m_bIsFloating && !w->isHidden() && w->m_bPinned && !w->m_bNoFocus) + CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; + if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && !w->isHidden() && w->m_bPinned && !w->m_bNoFocus) return w.get(); } for (auto& w : m_vWindows | std::views::reverse) { - wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; - if (wlr_box_contains_point(&box, m_sWLRCursor->x, m_sWLRCursor->y) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && + CBox box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; + if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y}) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_bNoFocus) return w.get(); } @@ -844,8 +840,9 @@ wlr_surface* CCompositor::vectorWindowToSurface(const Vector2D& pos, CWindow* pW double subx, suby; // calc for oversized windows... fucking bullshit, again. - wlr_box geom; - wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom); + CBox geom; + wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, geom.pWlr()); + geom.applyFromWlr(); const auto PFOUND = wlr_xdg_surface_surface_at(PSURFACE, pos.x - pWindow->m_vRealPosition.vec().x + geom.x, pos.y - pWindow->m_vRealPosition.vec().y + geom.y, &subx, &suby); @@ -886,8 +883,9 @@ Vector2D CCompositor::vectorToSurfaceLocal(const Vector2D& vec, CWindow* pWindow }, &iterData); - wlr_box geom = {0}; - wlr_xdg_surface_get_geometry(PSURFACE, &geom); + CBox geom = {}; + wlr_xdg_surface_get_geometry(PSURFACE, geom.pWlr()); + geom.applyFromWlr(); if (std::get<1>(iterData) == -1337 && std::get<2>(iterData) == -1337) return vec - pWindow->m_vRealPosition.goalv(); diff --git a/src/SharedDefs.hpp b/src/SharedDefs.hpp index 068d61f6..c060ac26 100644 --- a/src/SharedDefs.hpp +++ b/src/SharedDefs.hpp @@ -26,4 +26,18 @@ enum eRenderStage struct SCallbackInfo { bool cancelled = false; /* on cancellable events, will cancel the event. */ +}; + +struct SWindowDecorationExtents { + Vector2D topLeft; + Vector2D bottomRight; + + // + SWindowDecorationExtents operator*(const double& scale) const { + return SWindowDecorationExtents{topLeft * scale, bottomRight * scale}; + } + + SWindowDecorationExtents floor() { + return {topLeft.floor(), bottomRight.floor()}; + } }; \ No newline at end of file diff --git a/src/Window.cpp b/src/Window.cpp index f66a3139..7994b6cb 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -55,12 +55,12 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() { } if (m_pWLSurface.exists() && !m_bIsX11) { - wlr_box surfaceExtents = {0, 0, 0, 0}; + CBox surfaceExtents = {0, 0, 0, 0}; // TODO: this could be better, perhaps make a getFullWindowRegion? wlr_xdg_surface_for_each_popup_surface( m_uSurface.xdg, [](wlr_surface* surf, int sx, int sy, void* data) { - wlr_box* pSurfaceExtents = (wlr_box*)data; + CBox* pSurfaceExtents = (CBox*)data; if (sx < pSurfaceExtents->x) pSurfaceExtents->x = sx; if (sy < pSurfaceExtents->y) @@ -88,21 +88,21 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() { return maxExtents; } -wlr_box CWindow::getFullWindowBoundingBox() { +CBox CWindow::getFullWindowBoundingBox() { if (m_sAdditionalConfigData.dimAround) { const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); return {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; } - auto maxExtents = getFullWindowExtents(); + auto maxExtents = getFullWindowExtents(); - wlr_box finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y, - m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y}; + CBox finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y, + m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y}; return finalBox; } -wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() { +CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() { const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); @@ -113,7 +113,7 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() { POS = PMONITOR->vecPosition; SIZE = PMONITOR->vecSize; - return wlr_box{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y}; + return CBox{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y}; } if (DELTALESSTHAN(POS.y - PMONITOR->vecPosition.y, PMONITOR->vecReservedTopLeft.y, 1)) { @@ -131,10 +131,10 @@ wlr_box CWindow::getWindowIdealBoundingBoxIgnoreReserved() { SIZE.y += PMONITOR->vecReservedBottomRight.y; } - return wlr_box{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y}; + return CBox{(int)POS.x, (int)POS.y, (int)SIZE.x, (int)SIZE.y}; } -wlr_box CWindow::getWindowInputBox() { +CBox CWindow::getWindowInputBox() { const int BORDERSIZE = getRealBorderSize(); if (m_sAdditionalConfigData.dimAround) { @@ -165,13 +165,13 @@ wlr_box CWindow::getWindowInputBox() { } // Add extents to the real base BB and return - wlr_box finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y, - m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y}; + CBox finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y, + m_vRealSize.vec().x + maxExtents.topLeft.x + maxExtents.bottomRight.x, m_vRealSize.vec().y + maxExtents.topLeft.y + maxExtents.bottomRight.y}; return finalBox; } -wlr_box CWindow::getWindowMainSurfaceBox() { +CBox CWindow::getWindowMainSurfaceBox() { return {m_vRealPosition.vec().x, m_vRealPosition.vec().y, m_vRealSize.vec().x, m_vRealSize.vec().y}; } @@ -657,9 +657,9 @@ bool CWindow::isInCurvedCorner(double x, double y) { void findExtensionForVector2D(wlr_surface* surface, int x, int y, void* data) { const auto DATA = (SExtensionFindingData*)data; - wlr_box box = {DATA->origin.x + x, DATA->origin.y + y, surface->current.width, surface->current.height}; + CBox box = {DATA->origin.x + x, DATA->origin.y + y, surface->current.width, surface->current.height}; - if (wlr_box_contains_point(&box, DATA->vec.x, DATA->vec.y)) + if (box.containsPoint(DATA->vec)) *DATA->found = surface; } diff --git a/src/Window.hpp b/src/Window.hpp index 624d3325..dbfa2e04 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -11,14 +11,16 @@ #include "macros.hpp" #include "managers/XWaylandManager.hpp" -enum eIdleInhibitMode { +enum eIdleInhibitMode +{ IDLEINHIBIT_NONE = 0, IDLEINHIBIT_ALWAYS, IDLEINHIBIT_FULLSCREEN, IDLEINHIBIT_FOCUS }; -enum eGroupRules { +enum eGroupRules +{ // effective only during first map, except for _ALWAYS variant GROUP_NONE = 0, GROUP_SET = 1 << 0, // Open as new group or add to focused group @@ -334,11 +336,11 @@ class CWindow { } // methods - wlr_box getFullWindowBoundingBox(); + CBox getFullWindowBoundingBox(); SWindowDecorationExtents getFullWindowExtents(); - wlr_box getWindowInputBox(); - wlr_box getWindowMainSurfaceBox(); - wlr_box getWindowIdealBoundingBoxIgnoreReserved(); + CBox getWindowInputBox(); + CBox getWindowMainSurfaceBox(); + CBox getWindowIdealBoundingBoxIgnoreReserved(); void updateWindowDecos(); pid_t getPID(); IHyprWindowDecoration* getDecorationByType(eDecorationType); diff --git a/src/debug/HyprDebugOverlay.cpp b/src/debug/HyprDebugOverlay.cpp index 741f6e18..b5f7e1f2 100644 --- a/src/debug/HyprDebugOverlay.cpp +++ b/src/debug/HyprDebugOverlay.cpp @@ -233,6 +233,6 @@ void CHyprDebugOverlay::draw() { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA); - wlr_box pMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y}; + CBox pMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y}; g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f); } diff --git a/src/debug/HyprDebugOverlay.hpp b/src/debug/HyprDebugOverlay.hpp index 03027018..f3beab45 100644 --- a/src/debug/HyprDebugOverlay.hpp +++ b/src/debug/HyprDebugOverlay.hpp @@ -24,7 +24,7 @@ class CHyprMonitorDebugOverlay { std::deque m_dLastAnimationTicks; std::chrono::high_resolution_clock::time_point m_tpLastFrame; CMonitor* m_pMonitor = nullptr; - wlr_box m_wbLastDrawnBox; + CBox m_wbLastDrawnBox; friend class CHyprRenderer; }; diff --git a/src/debug/HyprNotificationOverlay.cpp b/src/debug/HyprNotificationOverlay.cpp index f82ca9bb..12f7a575 100644 --- a/src/debug/HyprNotificationOverlay.cpp +++ b/src/debug/HyprNotificationOverlay.cpp @@ -50,7 +50,7 @@ void CHyprNotificationOverlay::addNotification(const std::string& text, const CC } } -wlr_box CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) { +CBox CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) { static constexpr auto ANIM_DURATION_MS = 600.0; static constexpr auto ANIM_LAG_MS = 100.0; static constexpr auto NOTIF_LEFTBAR_SIZE = 5.0; @@ -170,7 +170,7 @@ wlr_box CHyprNotificationOverlay::drawNotifications(CMonitor* pMonitor) { // cleanup notifs std::erase_if(m_dNotifications, [](const auto& notif) { return notif->started.getMillis() > notif->timeMs; }); - return wlr_box{(int)(pMonitor->vecPosition.x + pMonitor->vecSize.x - maxWidth - 20), (int)pMonitor->vecPosition.y, (int)maxWidth + 20, (int)offsetY + 10}; + return CBox{(int)(pMonitor->vecPosition.x + pMonitor->vecSize.x - maxWidth - 20), (int)pMonitor->vecPosition.y, (int)maxWidth + 20, (int)offsetY + 10}; } void CHyprNotificationOverlay::draw(CMonitor* pMonitor) { @@ -201,7 +201,7 @@ void CHyprNotificationOverlay::draw(CMonitor* pMonitor) { cairo_surface_flush(m_pCairoSurface); - wlr_box damage = drawNotifications(pMonitor); + CBox damage = drawNotifications(pMonitor); g_pHyprRenderer->damageBox(&damage); g_pHyprRenderer->damageBox(&m_bLastDamage); @@ -224,6 +224,6 @@ void CHyprNotificationOverlay::draw(CMonitor* pMonitor) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA); - wlr_box pMonBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y}; + CBox pMonBox = {0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y}; g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f); } \ No newline at end of file diff --git a/src/debug/HyprNotificationOverlay.hpp b/src/debug/HyprNotificationOverlay.hpp index 462bbde1..46a9a3d0 100644 --- a/src/debug/HyprNotificationOverlay.hpp +++ b/src/debug/HyprNotificationOverlay.hpp @@ -44,8 +44,8 @@ class CHyprNotificationOverlay { void addNotification(const std::string& text, const CColor& color, const float timeMs, const eIcons icon = ICON_NONE); private: - wlr_box drawNotifications(CMonitor* pMonitor); - wlr_box m_bLastDamage; + CBox drawNotifications(CMonitor* pMonitor); + CBox m_bLastDamage; std::deque> m_dNotifications; diff --git a/src/events/Layers.cpp b/src/events/Layers.cpp index 5762e21a..5f295408 100644 --- a/src/events/Layers.cpp +++ b/src/events/Layers.cpp @@ -95,8 +95,8 @@ void Events::listener_destroyLayerSurface(void* owner, void* data) { PMONITOR->scheduledRecalc = true; // and damage - wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, - layersurface->geometry.height}; + CBox geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, + layersurface->geometry.height}; g_pHyprRenderer->damageBox(&geomFixed); } @@ -157,8 +157,8 @@ void Events::listener_mapLayerSurface(void* owner, void* data) { layersurface->position = Vector2D(layersurface->geometry.x, layersurface->geometry.y); - wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, - layersurface->geometry.height}; + CBox geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, + layersurface->geometry.height}; g_pHyprRenderer->damageBox(&geomFixed); const auto WORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); const bool FULLSCREEN = WORKSPACE->m_bHasFullscreenWindow && WORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL; @@ -247,8 +247,8 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) { } } - wlr_box geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, - layersurface->geometry.height}; + CBox geomFixed = {layersurface->geometry.x + PMONITOR->vecPosition.x, layersurface->geometry.y + PMONITOR->vecPosition.y, layersurface->geometry.width, + layersurface->geometry.height}; g_pHyprRenderer->damageBox(&geomFixed); geomFixed = {layersurface->geometry.x + (int)PMONITOR->vecPosition.x, layersurface->geometry.y + (int)PMONITOR->vecPosition.y, @@ -270,7 +270,7 @@ void Events::listener_commitLayerSurface(void* owner, void* data) { if (layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || layersurface->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM) g_pHyprOpenGL->markBlurDirtyForMonitor(PMONITOR); // so that blur is recalc'd - wlr_box geomFixed = {layersurface->geometry.x, layersurface->geometry.y, layersurface->geometry.width, layersurface->geometry.height}; + CBox geomFixed = {layersurface->geometry.x, layersurface->geometry.y, layersurface->geometry.width, layersurface->geometry.height}; g_pHyprRenderer->damageBox(&geomFixed); // fix if it changed its mon diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index f6375edd..9155fe87 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -28,8 +28,9 @@ void Events::listener_change(wl_listener* listener, void* data) { const auto CONFIGHEAD = wlr_output_configuration_head_v1_create(CONFIG, m->output); - wlr_box BOX; - wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, m->output, &BOX); + CBox BOX; + wlr_output_layout_get_box(g_pCompositor->m_sWLROutputLayout, m->output, BOX.pWlr()); + BOX.applyFromWlr(); //m->vecSize.x = BOX.width; // m->vecSize.y = BOX.height; diff --git a/src/events/Popups.cpp b/src/events/Popups.cpp index 559c8410..c8898c3b 100644 --- a/src/events/Popups.cpp +++ b/src/events/Popups.cpp @@ -64,9 +64,9 @@ void createNewPopup(wlr_xdg_popup* popup, SXDGPopup* pHyprPopup) { const auto PMONITOR = g_pCompositor->m_pLastMonitor; - wlr_box box = {.x = PMONITOR->vecPosition.x - pHyprPopup->lx, .y = PMONITOR->vecPosition.y - pHyprPopup->ly, .width = PMONITOR->vecSize.x, .height = PMONITOR->vecSize.y}; + CBox box = {PMONITOR->vecPosition.x - pHyprPopup->lx, PMONITOR->vecPosition.y - pHyprPopup->ly, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; - wlr_xdg_popup_unconstrain_from_box(popup, &box); + wlr_xdg_popup_unconstrain_from_box(popup, box.pWlr()); pHyprPopup->monitor = PMONITOR; @@ -159,8 +159,9 @@ void Events::listener_mapPopupXDG(void* owner, void* data) { int lx = 0, ly = 0; addPopupGlobalCoords(PPOPUP, &lx, &ly); - wlr_box extents; - wlr_surface_get_extends(PPOPUP->popup->base->surface, &extents); + CBox extents; + wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr()); + extents.applyFromWlr(); g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2); @@ -180,17 +181,18 @@ void Events::listener_repositionPopupXDG(void* owner, void* data) { int lx = 0, ly = 0; addPopupGlobalCoords(PPOPUP, &lx, &ly); - wlr_box extents; - wlr_surface_get_extends(PPOPUP->popup->base->surface, &extents); + CBox extents; + wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr()); + extents.applyFromWlr(); PPOPUP->lastPos = {lx - extents.x, ly - extents.y}; PPOPUP->repositionRequested = true; const auto PMONITOR = g_pCompositor->m_pLastMonitor; - wlr_box box = {PMONITOR->vecPosition.x - lx + PPOPUP->popup->current.geometry.x, PMONITOR->vecPosition.y - ly + PPOPUP->popup->current.geometry.y, PMONITOR->vecSize.x, - PMONITOR->vecSize.y}; - wlr_xdg_popup_unconstrain_from_box(PPOPUP->popup, &box); + CBox box = {PMONITOR->vecPosition.x - lx + PPOPUP->popup->current.geometry.x, PMONITOR->vecPosition.y - ly + PPOPUP->popup->current.geometry.y, PMONITOR->vecSize.x, + PMONITOR->vecSize.y}; + wlr_xdg_popup_unconstrain_from_box(PPOPUP->popup, box.pWlr()); } void Events::listener_unmapPopupXDG(void* owner, void* data) { @@ -207,8 +209,9 @@ void Events::listener_unmapPopupXDG(void* owner, void* data) { int lx = 0, ly = 0; addPopupGlobalCoords(PPOPUP, &lx, &ly); - wlr_box extents; - wlr_surface_get_extends(PPOPUP->popup->base->surface, &extents); + CBox extents; + wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr()); + extents.applyFromWlr(); g_pHyprRenderer->damageBox(lx - extents.x, ly - extents.y, extents.width + 2, extents.height + 2); @@ -233,8 +236,9 @@ void Events::listener_commitPopupXDG(void* owner, void* data) { int lx = 0, ly = 0; addPopupGlobalCoords(PPOPUP, &lx, &ly); - wlr_box extents; - wlr_surface_get_extends(PPOPUP->popup->base->surface, &extents); + CBox extents; + wlr_surface_get_extends(PPOPUP->popup->base->surface, extents.pWlr()); + extents.applyFromWlr(); if (PPOPUP->repositionRequested) g_pHyprRenderer->damageBox(PPOPUP->lastPos.x, PPOPUP->lastPos.y, extents.width + 2, extents.height + 2); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 59bd5fef..23559773 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -96,7 +96,7 @@ void Events::listener_mapWindow(void* owner, void* data) { if (PWORKSPACE->m_bDefaultPseudo) { PWINDOW->m_bIsPseudotiled = true; - wlr_box desiredGeometry = {0}; + CBox desiredGeometry = {0}; g_pXWaylandManager->getGeometryForWindow(PWINDOW, &desiredGeometry); PWINDOW->m_vPseudoSize = Vector2D(desiredGeometry.width, desiredGeometry.height); } diff --git a/src/helpers/Box.cpp b/src/helpers/Box.cpp new file mode 100644 index 00000000..450871cb --- /dev/null +++ b/src/helpers/Box.cpp @@ -0,0 +1,104 @@ +#include "Box.hpp" +wlr_box CBox::wlr() { + CBox rounded = roundInternal(); + m_bWlrBox = wlr_box{(int)rounded.x, (int)rounded.y, (int)rounded.w, (int)rounded.h}; + return m_bWlrBox; +} + +wlr_box* CBox::pWlr() { + CBox rounded = roundInternal(); + m_bWlrBox = wlr_box{(int)rounded.x, (int)rounded.y, (int)rounded.w, (int)rounded.h}; + return &m_bWlrBox; +} + +CBox& CBox::scale(double scale) { + x *= scale; + y *= scale; + w *= scale; + h *= scale; + + return *this; +} + +CBox& CBox::scale(const Vector2D& scale) { + x *= scale.x; + y *= scale.y; + w *= scale.x; + h *= scale.y; + + return *this; +} + +CBox& CBox::translate(const Vector2D& vec) { + x += vec.x; + y += vec.y; + + return *this; +} + +Vector2D CBox::middle() const { + return Vector2D{x + w / 2.0, y + h / 2.0}; +} + +bool CBox::containsPoint(const Vector2D& vec) const { + return VECINRECT(vec, x, y, x + w, y + h); +} + +bool CBox::empty() const { + return w == 0 || h == 0; +} + +CBox& CBox::applyFromWlr() { + x = m_bWlrBox.x; + y = m_bWlrBox.y; + w = m_bWlrBox.width; + h = m_bWlrBox.height; + + return *this; +} + +CBox& CBox::round() { + float newW = x + w - std::floor(x); + float newH = y + h - std::floor(y); + x = std::floor(x); + y = std::floor(y); + w = std::floor(newW); + h = std::floor(newH); + + return *this; +} + +CBox& CBox::transform(const wl_output_transform t, double w, double h) { + wlr_box_transform(&m_bWlrBox, pWlr(), t, w, h); + applyFromWlr(); + + return *this; +} + +CBox& CBox::addExtents(const SWindowDecorationExtents& e) { + x -= e.topLeft.x; + y -= e.topLeft.y; + w += e.topLeft.x + e.bottomRight.x; + h += e.topLeft.y + e.bottomRight.y; + + return *this; +} + +CBox& CBox::scaleFromCenter(double scale) { + double oldW = w, oldH = h; + + w *= scale; + h *= scale; + + x -= (w - oldW) / 2.0; + y -= (h - oldH) / 2.0; + + return *this; +} + +CBox CBox::roundInternal() { + float newW = x + w - std::floor(x); + float newH = y + h - std::floor(y); + + return CBox{std::floor(x), std::floor(y), std::floor(newW), std::floor(newH)}; +} \ No newline at end of file diff --git a/src/helpers/Box.hpp b/src/helpers/Box.hpp new file mode 100644 index 00000000..7a8aa939 --- /dev/null +++ b/src/helpers/Box.hpp @@ -0,0 +1,66 @@ +#pragma once + +#include +#include "Vector2D.hpp" +#include "../SharedDefs.hpp" + +class CBox { + public: + CBox(double x_, double y_, double w_, double h_) { + x = x_; + y = y_; + w = w_; + h = h_; + } + + CBox() { + w = 0; + h = 0; + } + + CBox(const wlr_box& box) { + x = box.x; + y = box.y; + w = box.width; + h = box.height; + } + + CBox(const double d) { + x = d; + y = d; + w = d; + h = d; + } + + wlr_box wlr(); + wlr_box* pWlr(); + + CBox& applyFromWlr(); + CBox& scale(double scale); + CBox& scaleFromCenter(double scale); + CBox& scale(const Vector2D& scale); + CBox& translate(const Vector2D& vec); + CBox& round(); + CBox& transform(const wl_output_transform t, double w, double h); + CBox& addExtents(const SWindowDecorationExtents& e); + + Vector2D middle() const; + + bool containsPoint(const Vector2D& vec) const; + bool empty() const; + + double x = 0, y = 0; + union { + double w; + double width; + }; + union { + double h; + double height; + }; + + private: + CBox roundInternal(); + + wlr_box m_bWlrBox; +}; \ No newline at end of file diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index b65f4a87..b3a8ade7 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -185,13 +185,6 @@ std::string escapeJSONStrings(const std::string& str) { return oss.str(); } -void scaleBox(wlr_box* box, float scale) { - box->width = std::round(box->width * scale); - box->height = std::round(box->height * scale); - box->x = std::round(box->x * scale); - box->y = std::round(box->y * scale); -} - std::string removeBeginEndSpacesTabs(std::string str) { if (str.empty()) return str; diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 499aa90f..3bb07f79 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -16,7 +16,6 @@ struct SCallstackFrameInfo { std::string absolutePath(const std::string&, const std::string&); void addWLSignal(wl_signal*, wl_listener*, void* pOwner, const std::string& ownerString); std::string escapeJSONStrings(const std::string& str); -void scaleBox(wlr_box*, float); std::string removeBeginEndSpacesTabs(std::string); bool isNumber(const std::string&, bool allowfloat = false); bool isDirection(const std::string&); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 6d6b40e0..9dbd2a3e 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -317,14 +317,14 @@ void CMonitor::addDamage(const CRegion* rg) { addDamage(const_cast(rg)->pixman()); } -void CMonitor::addDamage(const wlr_box* box) { +void CMonitor::addDamage(const CBox* box) { static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue; if (*PZOOMFACTOR != 1.f && g_pCompositor->getMonitorFromCursor() == this) { wlr_damage_ring_add_whole(&damage); g_pCompositor->scheduleFrameForMonitor(this); } - if (wlr_damage_ring_add_box(&damage, box)) + if (wlr_damage_ring_add_box(&damage, const_cast(box)->pWlr())) g_pCompositor->scheduleFrameForMonitor(this); } diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 5e861b50..10790b5e 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -113,7 +113,7 @@ class CMonitor { void onDisconnect(); void addDamage(const pixman_region32_t* rg); void addDamage(const CRegion* rg); - void addDamage(const wlr_box* box); + void addDamage(const CBox* box); void setMirror(const std::string&); bool isMirror(); float getDefaultScale(); diff --git a/src/helpers/Region.cpp b/src/helpers/Region.cpp index 5515e71e..fdf8a242 100644 --- a/src/helpers/Region.cpp +++ b/src/helpers/Region.cpp @@ -21,6 +21,10 @@ CRegion::CRegion(wlr_box* box) { pixman_region32_init_rect(&m_rRegion, box->x, box->y, box->width, box->height); } +CRegion::CRegion(CBox* box) { + pixman_region32_init_rect(&m_rRegion, box->x, box->y, box->w, box->h); +} + CRegion::CRegion(pixman_box32_t* box) { pixman_region32_init_rect(&m_rRegion, box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1); } @@ -100,7 +104,7 @@ std::vector CRegion::getRects() const { return result; } -wlr_box CRegion::getExtents() { +CBox CRegion::getExtents() { pixman_box32_t* box = pixman_region32_extents(&m_rRegion); return {box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1}; } diff --git a/src/helpers/Region.hpp b/src/helpers/Region.hpp index cc745f9e..94b639c9 100644 --- a/src/helpers/Region.hpp +++ b/src/helpers/Region.hpp @@ -15,6 +15,8 @@ class CRegion { CRegion(double x, double y, double w, double h); /* Create from a wlr_box */ CRegion(wlr_box* box); + /* Create from a CBox */ + CRegion(CBox* box); /* Create from a pixman_box32_t */ CRegion(pixman_box32_t* box); @@ -43,7 +45,7 @@ class CRegion { CRegion& translate(const Vector2D& vec); CRegion& invert(pixman_box32_t* box); CRegion& scale(float scale); - wlr_box getExtents(); + CBox getExtents(); bool containsPoint(const Vector2D& vec) const; bool empty() const; Vector2D closestPoint(const Vector2D& vec) const; @@ -51,7 +53,7 @@ class CRegion { std::vector getRects() const; pixman_region32_t* pixman() { - return &m_rRegion; + return &m_rRegion; } private: diff --git a/src/helpers/SubsurfaceTree.cpp b/src/helpers/SubsurfaceTree.cpp index c3716100..84ba5cbb 100644 --- a/src/helpers/SubsurfaceTree.cpp +++ b/src/helpers/SubsurfaceTree.cpp @@ -98,8 +98,9 @@ void SubsurfaceTree::destroySurfaceTree(SSurfaceTreeNode* pNode) { // damage if (pNode->pSurface && pNode->pSurface->exists()) { - wlr_box extents = {}; - wlr_surface_get_extends(pNode->pSurface->wlr(), &extents); + CBox extents = {}; + wlr_surface_get_extends(pNode->pSurface->wlr(), extents.pWlr()); + extents.applyFromWlr(); int lx = 0, ly = 0; addSurfaceGlobalOffset(pNode, &lx, &ly); @@ -198,7 +199,7 @@ void Events::listener_unmapSubsurface(void* owner, void* data) { int lx = 0, ly = 0; addSurfaceGlobalOffset(PNODE, &lx, &ly); - wlr_box extents = {lx, ly, 0, 0}; + CBox extents = {lx, ly, 0, 0}; extents.width = PNODE->pSurface->wlr()->current.width; extents.height = PNODE->pSurface->wlr()->current.height; diff --git a/src/helpers/Vector2D.hpp b/src/helpers/Vector2D.hpp index 3c5d4a2c..6112b8e4 100644 --- a/src/helpers/Vector2D.hpp +++ b/src/helpers/Vector2D.hpp @@ -22,6 +22,9 @@ class Vector2D { Vector2D operator-(const Vector2D& a) const { return Vector2D(this->x - a.x, this->y - a.y); } + Vector2D operator-() const { + return Vector2D(-this->x, -this->y); + } Vector2D operator*(const float& a) const { return Vector2D(this->x * a, this->y * a); } diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index e8647426..f7efbe98 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -33,7 +33,7 @@ struct SLayerSurface { DYNLISTENER(commitLayerSurface); DYNLISTENER(newPopup); - wlr_box geometry = {0, 0, 0, 0}; + CBox geometry = {0, 0, 0, 0}; Vector2D position; zwlr_layer_shell_v1_layer layer; @@ -65,12 +65,12 @@ class CMonitor; struct SRenderData { CMonitor* pMonitor; timespec* when; - int x, y; + double x, y; // for iters void* data = nullptr; wlr_surface* surface = nullptr; - int w, h; + double w, h; // for rounding bool dontRound = true; diff --git a/src/hyprerror/HyprError.cpp b/src/hyprerror/HyprError.cpp index 4f916139..6a91ba87 100644 --- a/src/hyprerror/HyprError.cpp +++ b/src/hyprerror/HyprError.cpp @@ -154,7 +154,7 @@ void CHyprError::draw() { const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor; - wlr_box monbox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y}; + CBox monbox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y}; m_bDamageBox.x = (int)PMONITOR->vecPosition.x; m_bDamageBox.y = (int)PMONITOR->vecPosition.y; diff --git a/src/hyprerror/HyprError.hpp b/src/hyprerror/HyprError.hpp index ff4e8577..cee648e2 100644 --- a/src/hyprerror/HyprError.hpp +++ b/src/hyprerror/HyprError.hpp @@ -23,7 +23,7 @@ class CHyprError { bool m_bIsCreated = false; CTexture m_tTexture; CAnimatedVariable m_fFadeOpacity; - wlr_box m_bDamageBox = {0, 0, 0, 0}; + CBox m_bDamageBox = {0, 0, 0, 0}; bool m_bMonitorChanged = false; }; diff --git a/src/includes.hpp b/src/includes.hpp index a70815dc..2ffb7710 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -145,3 +145,4 @@ extern "C" { #endif #include "helpers/Vector2D.hpp" +#include "helpers/Box.hpp" diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 2bbda858..f9f8ab59 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -6,7 +6,7 @@ void IHyprLayout::onWindowCreated(CWindow* pWindow, eDirection direction) { if (pWindow->m_bIsFloating) { onWindowCreatedFloating(pWindow); } else { - wlr_box desiredGeometry = {0}; + CBox desiredGeometry = {}; g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) { @@ -75,7 +75,7 @@ void IHyprLayout::onWindowRemovedFloating(CWindow* pWindow) { void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) { - wlr_box desiredGeometry = {0}; + CBox desiredGeometry = {0}; g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 0fbb2391..e3b7b7ab 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -141,8 +141,8 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc for (auto it = m_lMasterNodesData.begin(); it != m_lMasterNodesData.end(); ++it) { if (it->workspaceID != pWindow->m_iWorkspaceID) continue; - const wlr_box box = it->pWindow->getWindowIdealBoundingBoxIgnoreReserved(); - if (wlr_box_contains_point(&box, MOUSECOORDS.x, MOUSECOORDS.y)) { + const CBox box = it->pWindow->getWindowIdealBoundingBoxIgnoreReserved(); + if (box.containsPoint(MOUSECOORDS)) { switch (orientation) { case ORIENTATION_LEFT: case ORIENTATION_RIGHT: diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index a7d05030..1dc8e2c6 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -81,7 +81,7 @@ void CAnimationManager::tick() { CMonitor* PMONITOR = nullptr; bool animationsDisabled = animGlobalDisabled; - wlr_box WLRBOXPREV = {0, 0, 0, 0}; + CBox WLRBOXPREV = {0, 0, 0, 0}; if (PWINDOW) { WLRBOXPREV = PWINDOW->getFullWindowBoundingBox(); PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); @@ -236,7 +236,7 @@ void CAnimationManager::tick() { BORDERSIZE + ROUNDINGSIZE); // bottom // damage for new box - const wlr_box WLRBOXNEW = {PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealSize.vec().y}; + const CBox WLRBOXNEW = {PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealSize.vec().y}; g_pHyprRenderer->damageBox(WLRBOXNEW.x - BORDERSIZE, WLRBOXNEW.y - BORDERSIZE, WLRBOXNEW.width + 2 * BORDERSIZE, BORDERSIZE + ROUNDINGSIZE); // top g_pHyprRenderer->damageBox(WLRBOXNEW.x - BORDERSIZE, WLRBOXNEW.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, WLRBOXNEW.height + 2 * BORDERSIZE); // left g_pHyprRenderer->damageBox(WLRBOXNEW.x + WLRBOXNEW.width - ROUNDINGSIZE, WLRBOXNEW.y - BORDERSIZE, BORDERSIZE + ROUNDINGSIZE, @@ -255,9 +255,8 @@ void CAnimationManager::tick() { if (PDECO) { const auto EXTENTS = PDECO->getWindowDecorationExtents(); - wlr_box dmg = {PWINDOW->m_vRealPosition.vec().x - EXTENTS.topLeft.x, PWINDOW->m_vRealPosition.vec().y - EXTENTS.topLeft.y, - PWINDOW->m_vRealSize.vec().x + EXTENTS.topLeft.x + EXTENTS.bottomRight.x, - PWINDOW->m_vRealSize.vec().y + EXTENTS.topLeft.y + EXTENTS.bottomRight.y}; + CBox dmg = {PWINDOW->m_vRealPosition.vec().x - EXTENTS.topLeft.x, PWINDOW->m_vRealPosition.vec().y - EXTENTS.topLeft.y, + PWINDOW->m_vRealSize.vec().x + EXTENTS.topLeft.x + EXTENTS.bottomRight.x, PWINDOW->m_vRealSize.vec().y + EXTENTS.topLeft.y + EXTENTS.bottomRight.y}; if (!*PSHADOWIGNOREWINDOW) { // easy, damage the entire box diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index a40647fa..04fbaf21 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -74,7 +74,7 @@ void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) { g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID)->m_pLastFocusedWindow = pWindow; } -void CHyprXWaylandManager::getGeometryForWindow(CWindow* pWindow, wlr_box* pbox) { +void CHyprXWaylandManager::getGeometryForWindow(CWindow* pWindow, CBox* pbox) { if (pWindow->m_bIsX11) { const auto SIZEHINTS = pWindow->m_uSurface.xwayland->size_hints; @@ -89,8 +89,10 @@ void CHyprXWaylandManager::getGeometryForWindow(CWindow* pWindow, wlr_box* pbox) pbox->width = pWindow->m_uSurface.xwayland->width; pbox->height = pWindow->m_uSurface.xwayland->height; } - } else - wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, pbox); + } else { + wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, pbox->pWlr()); + pbox->applyFromWlr(); + } } std::string CHyprXWaylandManager::getTitle(CWindow* pWindow) { diff --git a/src/managers/XWaylandManager.hpp b/src/managers/XWaylandManager.hpp index 807f0593..e41313e0 100644 --- a/src/managers/XWaylandManager.hpp +++ b/src/managers/XWaylandManager.hpp @@ -15,7 +15,7 @@ class CHyprXWaylandManager { wlr_surface* getWindowSurface(CWindow*); void activateSurface(wlr_surface*, bool); void activateWindow(CWindow*, bool); - void getGeometryForWindow(CWindow*, wlr_box*); + void getGeometryForWindow(CWindow*, CBox*); std::string getTitle(CWindow*); std::string getAppIDClass(CWindow*); void sendCloseWindow(CWindow*); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index dcbf4e3c..d7733e96 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -599,8 +599,8 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { // TODO detect click on LS properly if (*PRESIZEONBORDER && !m_bLastFocusOnLS) { if (w && !w->m_bIsFullscreen) { - const wlr_box real = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; - if ((!wlr_box_contains_point(&real, mouseCoords.x, mouseCoords.y) || w->isInCurvedCorner(mouseCoords.x, mouseCoords.y)) && !w->hasPopupAt(mouseCoords)) { + const CBox real = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; + if ((!real.containsPoint(mouseCoords) || w->isInCurvedCorner(mouseCoords.x, mouseCoords.y)) && !w->hasPopupAt(mouseCoords)) { g_pKeybindManager->resizeWithBorder(e); return; } @@ -675,8 +675,8 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) { const auto pWindow = g_pCompositor->vectorToWindowIdeal(MOUSECOORDS); if (*PGROUPBARSCROLLING && pWindow && !pWindow->m_bIsFullscreen && !pWindow->hasPopupAt(MOUSECOORDS) && pWindow->m_sGroupData.pNextWindow) { - const wlr_box box = pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents(); - if (wlr_box_contains_point(&box, MOUSECOORDS.x, MOUSECOORDS.y)) { + const CBox box = pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents(); + if (box.containsPoint(MOUSECOORDS)) { if (e->delta > 0) pWindow->setGroupCurrent(pWindow->m_sGroupData.pNextWindow); else @@ -1207,7 +1207,7 @@ void CInputManager::updateDragIcon() { switch (m_sDrag.dragIcon->drag->grab_type) { case WLR_DRAG_GRAB_KEYBOARD: break; case WLR_DRAG_GRAB_KEYBOARD_POINTER: { - wlr_box box = {m_sDrag.pos.x - 2, m_sDrag.pos.y - 2, m_sDrag.dragIcon->surface->current.width + 4, m_sDrag.dragIcon->surface->current.height + 4}; + CBox box = {m_sDrag.pos.x - 2, m_sDrag.pos.y - 2, m_sDrag.dragIcon->surface->current.width + 4, m_sDrag.dragIcon->surface->current.height + 4}; g_pHyprRenderer->damageBox(&box); m_sDrag.pos = getMouseCoordsInternal(); break; @@ -1474,9 +1474,9 @@ void CInputManager::setTabletConfigs() { const auto REGION_POS = g_pConfigManager->getDeviceVec(t.name, "region_position", "input:tablet:region_position"); const auto REGION_SIZE = g_pConfigManager->getDeviceVec(t.name, "region_size", "input:tablet:region_size"); - const auto REGION = wlr_box{REGION_POS.x, REGION_POS.y, REGION_SIZE.x, REGION_SIZE.y}; - if (!wlr_box_empty(®ION)) - wlr_cursor_map_input_to_region(g_pCompositor->m_sWLRCursor, t.wlrDevice, ®ION); + auto regionBox = CBox{REGION_POS.x, REGION_POS.y, REGION_SIZE.x, REGION_SIZE.y}; + if (!regionBox.empty()) + wlr_cursor_map_input_to_region(g_pCompositor->m_sWLRCursor, t.wlrDevice, regionBox.pWlr()); } } } @@ -1621,14 +1621,14 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) { // give a small leeway (10 px) for corner icon const auto CORNER = *PROUNDING + BORDERSIZE + 10; const auto mouseCoords = getMouseCoordsInternal(); - wlr_box box = w->getWindowMainSurfaceBox(); + CBox box = w->getWindowMainSurfaceBox(); eBorderIconDirection direction = BORDERICON_NONE; - wlr_box boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE), - box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; + CBox boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE), + box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; if (w->hasPopupAt(mouseCoords)) direction = BORDERICON_NONE; - else if (!wlr_box_contains_point(&boxFullGrabInput, mouseCoords.x, mouseCoords.y) || (!m_lCurrentlyHeldButtons.empty() && !currentlyDraggedWindow)) + else if (!boxFullGrabInput.containsPoint(mouseCoords) || (!m_lCurrentlyHeldButtons.empty() && !currentlyDraggedWindow)) direction = BORDERICON_NONE; else { @@ -1647,7 +1647,7 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) { if (onDeco) direction = BORDERICON_NONE; else { - if (wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y)) { + if (box.containsPoint(mouseCoords)) { if (!w->isInCurvedCorner(mouseCoords.x, mouseCoords.y)) { direction = BORDERICON_NONE; } else { diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index 4af17096..5b6df08d 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -178,7 +178,7 @@ void CInputMethodRelay::updateInputPopup(SIMEPopup* pPopup) { bool cursorRect = PFOCUSEDTI->pWlrInput ? PFOCUSEDTI->pWlrInput->current.features & WLR_TEXT_INPUT_V3_FEATURE_CURSOR_RECTANGLE : true; const auto PFOCUSEDSURFACE = focusedSurface(PFOCUSEDTI); - auto cursorBox = PFOCUSEDTI->pWlrInput ? PFOCUSEDTI->pWlrInput->current.cursor_rectangle : PFOCUSEDTI->pV1Input->cursorRectangle; + CBox cursorBox = PFOCUSEDTI->pWlrInput ? PFOCUSEDTI->pWlrInput->current.cursor_rectangle : PFOCUSEDTI->pV1Input->cursorRectangle; CMonitor* pMonitor = nullptr; Vector2D parentPos; @@ -209,7 +209,7 @@ void CInputMethodRelay::updateInputPopup(SIMEPopup* pPopup) { if (!pMonitor) return; - wlr_box finalBox = cursorBox; + CBox finalBox = cursorBox; if (cursorBox.y + parentPos.y + pPopup->pSurface->surface->current.height + finalBox.height > pMonitor->vecPosition.y + pMonitor->vecSize.y) finalBox.y -= pPopup->pSurface->surface->current.height + finalBox.height; @@ -225,7 +225,7 @@ void CInputMethodRelay::updateInputPopup(SIMEPopup* pPopup) { pPopup->lastSize = Vector2D(pPopup->pSurface->surface->current.width, pPopup->pSurface->surface->current.height); - wlr_input_popup_surface_v2_send_text_input_rectangle(pPopup->pSurface, &finalBox); + wlr_input_popup_surface_v2_send_text_input_rectangle(pPopup->pSurface, finalBox.pWlr()); damagePopup(pPopup); } diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index aaec0fab..63ba8832 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -183,7 +183,7 @@ void CScreencopyProtocolManager::removeFrame(SScreencopyFrame* frame, bool force m_lFrames.remove(*frame); } -void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* output, wlr_box box) { +void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* output, CBox box) { const auto PCLIENT = clientFromResource(resource); const auto PFRAME = &m_lFrames.emplace_back(); @@ -239,8 +239,7 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r } int ow, oh; wlr_output_effective_resolution(PFRAME->pMonitor->output, &ow, &oh); - wlr_box_transform(&PFRAME->box, &PFRAME->box, PFRAME->pMonitor->transform, ow, oh); - scaleBox(&PFRAME->box, PFRAME->pMonitor->scale); + PFRAME->box.transform(PFRAME->pMonitor->transform, ow, oh).scale(PFRAME->pMonitor->scale); PFRAME->shmStride = (PSHMINFO->bpp / 8) * PFRAME->box.width; diff --git a/src/protocols/Screencopy.hpp b/src/protocols/Screencopy.hpp index 3af75544..e3d1e22a 100644 --- a/src/protocols/Screencopy.hpp +++ b/src/protocols/Screencopy.hpp @@ -46,7 +46,7 @@ struct SScreencopyFrame { uint32_t shmFormat = 0; uint32_t dmabufFormat = 0; - wlr_box box = {0}; + CBox box = {}; int shmStride = 0; bool overlayCursor = false; @@ -73,7 +73,7 @@ class CScreencopyProtocolManager { void removeFrame(SScreencopyFrame* frame, bool force = false); void displayDestroy(); - void captureOutput(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* output, wlr_box box = {0, 0, 0, 0}); + void captureOutput(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, wl_resource* output, CBox box = {0, 0, 0, 0}); void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer); diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp index 9156da12..d69a79ca 100644 --- a/src/protocols/TextInputV1.cpp +++ b/src/protocols/TextInputV1.cpp @@ -200,7 +200,7 @@ void CTextInputV1ProtocolManager::handleSetContentType(wl_client* client, wl_res void CTextInputV1ProtocolManager::handleSetCursorRectangle(wl_client* client, wl_resource* resource, int32_t x, int32_t y, int32_t width, int32_t height) { const auto PTI = tiFromResource(resource); - PTI->cursorRectangle = wlr_box{x, y, width, height}; + PTI->cursorRectangle = CBox{x, y, width, height}; } void CTextInputV1ProtocolManager::handleSetPreferredLanguage(wl_client* client, wl_resource* resource, const char* language) { diff --git a/src/protocols/TextInputV1.hpp b/src/protocols/TextInputV1.hpp index f714b24c..b279763d 100644 --- a/src/protocols/TextInputV1.hpp +++ b/src/protocols/TextInputV1.hpp @@ -39,9 +39,9 @@ struct STextInputV1 { uint32_t purpose = 0; } pendingContentType; - wlr_box cursorRectangle = {0, 0, 0, 0}; + CBox cursorRectangle = {0, 0, 0, 0}; - bool operator==(const STextInputV1& other) { + bool operator==(const STextInputV1& other) { return other.client == client && other.resourceCaller == resourceCaller && other.resourceImpl == resourceImpl; } }; diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 3515d652..11287660 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -201,7 +201,7 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou PFRAME->box = {0, 0, (int)(PFRAME->pWindow->m_vRealSize.vec().x * PMONITOR->scale), (int)(PFRAME->pWindow->m_vRealSize.vec().y * PMONITOR->scale)}; int ow, oh; wlr_output_effective_resolution(PMONITOR->output, &ow, &oh); - wlr_box_transform(&PFRAME->box, &PFRAME->box, PMONITOR->transform, ow, oh); + PFRAME->box.transform(PMONITOR->transform, ow, oh); PFRAME->shmStride = (PSHMINFO->bpp / 8) * PFRAME->box.width; @@ -301,9 +301,9 @@ void CToplevelExportProtocolManager::onOutputCommit(CMonitor* pMonitor, wlr_outp if (PMONITOR != g_pCompositor->getMonitorFromID(f->pWindow->m_iMonitorID)) continue; - wlr_box geometry = {f->pWindow->m_vRealPosition.vec().x, f->pWindow->m_vRealPosition.vec().y, f->pWindow->m_vRealSize.vec().x, f->pWindow->m_vRealSize.vec().y}; + CBox geometry = {f->pWindow->m_vRealPosition.vec().x, f->pWindow->m_vRealPosition.vec().y, f->pWindow->m_vRealSize.vec().x, f->pWindow->m_vRealSize.vec().y}; - if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, &geometry)) + if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, geometry.pWlr())) continue; shareFrame(f); @@ -448,7 +448,7 @@ bool CToplevelExportProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame, ti g_pHyprOpenGL->bindWlrOutputFb(); - wlr_box monbox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y}; + CBox monbox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y}; g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 1.f); g_pHyprOpenGL->end(); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index d8637a53..0011e636 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -172,17 +172,14 @@ void CHyprOpenGLImpl::end() { saveBufferForMirror(); // save with original damage region glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb); - wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; + CBox monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; if (m_RenderData.mouseZoomFactor != 1.f) { const auto ZOOMCENTER = m_RenderData.mouseZoomUseMouse ? (g_pInputManager->getMouseCoordsInternal() - m_RenderData.pMonitor->vecPosition) * m_RenderData.pMonitor->scale : m_RenderData.pMonitor->vecTransformedSize / 2.f; - monbox.x -= ZOOMCENTER.x; - monbox.y -= ZOOMCENTER.y; - scaleBox(&monbox, m_RenderData.mouseZoomFactor); - monbox.x += *PZOOMRIGID ? m_RenderData.pMonitor->vecTransformedSize.x / 2 : ZOOMCENTER.x; - monbox.y += *PZOOMRIGID ? m_RenderData.pMonitor->vecTransformedSize.y / 2 : ZOOMCENTER.y; + + monbox.translate(-ZOOMCENTER).scale(m_RenderData.mouseZoomFactor).translate(*PZOOMRIGID ? m_RenderData.pMonitor->vecTransformedSize / 2.0 : ZOOMCENTER); if (monbox.x > 0) monbox.x = 0; @@ -418,7 +415,7 @@ void CHyprOpenGLImpl::clear(const CColor& color) { } } - scissor((wlr_box*)nullptr); + scissor((CBox*)nullptr); } void CHyprOpenGLImpl::blend(bool enabled) { @@ -431,7 +428,7 @@ void CHyprOpenGLImpl::blend(bool enabled) { m_bBlend = enabled; } -void CHyprOpenGLImpl::scissor(const wlr_box* pBox, bool transform) { +void CHyprOpenGLImpl::scissor(const CBox* pBox, bool transform) { RASSERT(m_RenderData.pMonitor, "Tried to scissor without begin()!"); if (!pBox) { @@ -439,14 +436,14 @@ void CHyprOpenGLImpl::scissor(const wlr_box* pBox, bool transform) { return; } - wlr_box newBox = *pBox; + CBox newBox = *pBox; if (transform) { int w, h; wlr_output_transformed_resolution(m_RenderData.pMonitor->output, &w, &h); const auto TR = wlr_output_transform_invert(m_RenderData.pMonitor->transform); - wlr_box_transform(&newBox, &newBox, TR, w, h); + newBox.transform(TR, w, h); } glScissor(newBox.x, newBox.y, newBox.width, newBox.height); @@ -461,22 +458,22 @@ void CHyprOpenGLImpl::scissor(const pixman_box32* pBox, bool transform) { return; } - wlr_box newBox = {pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1}; + CBox newBox = {pBox->x1, pBox->y1, pBox->x2 - pBox->x1, pBox->y2 - pBox->y1}; scissor(&newBox, transform); } void CHyprOpenGLImpl::scissor(const int x, const int y, const int w, const int h, bool transform) { - wlr_box box = {x, y, w, h}; + CBox box = {x, y, w, h}; scissor(&box, transform); } -void CHyprOpenGLImpl::renderRect(wlr_box* box, const CColor& col, int round) { +void CHyprOpenGLImpl::renderRect(CBox* box, const CColor& col, int round) { if (!m_RenderData.damage.empty()) renderRectWithDamage(box, col, &m_RenderData.damage, round); } -void CHyprOpenGLImpl::renderRectWithBlur(wlr_box* box, const CColor& col, int round, float blurA) { +void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round, float blurA) { if (m_RenderData.damage.empty()) return; @@ -489,7 +486,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(wlr_box* box, const CColor& col, int ro m_RenderData.pCurrentMonData->primaryFB.bind(); // make a stencil for rounded corners to work with blur - scissor((wlr_box*)nullptr); // allow the entire window and stencil to render + scissor((CBox*)nullptr); // allow the entire window and stencil to render glClearStencil(0); glClear(GL_STENCIL_BUFFER_BIT); @@ -506,7 +503,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(wlr_box* box, const CColor& col, int ro glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); scissor(box); - wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; + CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; m_bEndFrame = true; // fix transformed const auto SAVEDRENDERMODIF = m_RenderData.renderModif; m_RenderData.renderModif = {}; // fix shit @@ -519,26 +516,24 @@ void CHyprOpenGLImpl::renderRectWithBlur(wlr_box* box, const CColor& col, int ro glDisable(GL_STENCIL_TEST); glStencilMask(-1); glStencilFunc(GL_ALWAYS, 1, 0xFF); - scissor((wlr_box*)nullptr); + scissor((CBox*)nullptr); renderRectWithDamage(box, col, &m_RenderData.damage, round); } -void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, CRegion* damage, int round) { +void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion* damage, int round) { RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); TRACY_GPU_ZONE("RenderRectWithDamage"); - wlr_box newBox = *box; - scaleBox(&newBox, m_RenderData.renderModif.scale); - newBox.x += m_RenderData.renderModif.translate.x; - newBox.y += m_RenderData.renderModif.translate.y; + CBox newBox = *box; + newBox.scale(m_RenderData.renderModif.scale).translate(m_RenderData.renderModif.translate); box = &newBox; float matrix[9]; - wlr_matrix_project_box(matrix, box, wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, + wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here float glMatrix[9]; @@ -556,9 +551,9 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, CReg // premultiply the color as well as we don't work with straight alpha glUniform4f(m_RenderData.pCurrentMonData->m_shQUAD.color, col.r * col.a, col.g * col.a, col.b * col.a, col.a); - wlr_box transformedBox; - wlr_box_transform(&transformedBox, box, wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, - m_RenderData.pMonitor->vecTransformedSize.y); + CBox transformedBox = *box; + transformedBox.transform(wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, + m_RenderData.pMonitor->vecTransformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height); @@ -592,22 +587,22 @@ void CHyprOpenGLImpl::renderRectWithDamage(wlr_box* box, const CColor& col, CReg glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shQUAD.posAttrib); } -void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, wlr_box* pBox, float alpha, int round, bool allowCustomUV) { +void CHyprOpenGLImpl::renderTexture(wlr_texture* tex, CBox* pBox, float alpha, int round, bool allowCustomUV) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); renderTexture(CTexture(tex), pBox, alpha, round, false, allowCustomUV); } -void CHyprOpenGLImpl::renderTexture(const CTexture& tex, wlr_box* pBox, float alpha, int round, bool discardActive, bool allowCustomUV) { +void CHyprOpenGLImpl::renderTexture(const CTexture& tex, CBox* pBox, float alpha, int round, bool discardActive, bool allowCustomUV) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); renderTextureInternalWithDamage(tex, pBox, alpha, &m_RenderData.damage, round, discardActive, false, allowCustomUV, true); - scissor((wlr_box*)nullptr); + scissor((CBox*)nullptr); } -void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_box* pBox, float alpha, CRegion* damage, int round, bool discardActive, bool noAA, - bool allowCustomUV, bool allowDim) { +void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox* pBox, float alpha, CRegion* damage, int round, bool discardActive, bool noAA, bool allowCustomUV, + bool allowDim) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!"); @@ -618,17 +613,15 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b if (m_RenderData.damage.empty()) return; - wlr_box newBox = *pBox; - scaleBox(&newBox, m_RenderData.renderModif.scale); - newBox.x += m_RenderData.renderModif.translate.x; - newBox.y += m_RenderData.renderModif.translate.y; + CBox newBox = *pBox; + newBox.scale(m_RenderData.renderModif.scale).translate(m_RenderData.renderModif.translate); static auto* const PDIMINACTIVE = &g_pConfigManager->getConfigValuePtr("decoration:dim_inactive")->intValue; // get transform const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); float matrix[9]; - wlr_matrix_project_box(matrix, &newBox, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix); + wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -711,9 +704,9 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b } } - wlr_box transformedBox; - wlr_box_transform(&transformedBox, &newBox, wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, - m_RenderData.pMonitor->vecTransformedSize.y); + CBox transformedBox = newBox; + transformedBox.transform(wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, + m_RenderData.pMonitor->vecTransformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height); @@ -774,7 +767,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, wlr_b glBindTexture(tex.m_iTarget, 0); } -void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, wlr_box* pBox) { +void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, CBox* pBox) { RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!"); @@ -783,15 +776,13 @@ void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, wlr_box* pBox) if (m_RenderData.damage.empty()) return; - wlr_box newBox = *pBox; - scaleBox(&newBox, m_RenderData.renderModif.scale); - newBox.x += m_RenderData.renderModif.translate.x; - newBox.y += m_RenderData.renderModif.translate.y; + CBox newBox = *pBox; + newBox.scale(m_RenderData.renderModif.scale).translate(m_RenderData.renderModif.translate); // get transform const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); float matrix[9]; - wlr_matrix_project_box(matrix, &newBox, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix); + wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -822,7 +813,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, wlr_box* pBox) glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } - scissor((wlr_box*)nullptr); + scissor((CBox*)nullptr); glDisableVertexAttribArray(shader->posAttrib); glDisableVertexAttribArray(shader->texAttrib); @@ -845,8 +836,8 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o // get transforms for the full monitor const auto TRANSFORM = wlr_output_transform_invert(m_RenderData.pMonitor->transform); float matrix[9]; - wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; - wlr_matrix_project_box(matrix, &MONITORBOX, TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix); + CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; + wlr_matrix_project_box(matrix, MONITORBOX.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -1138,7 +1129,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() { // make the fake dmg CRegion fakeDamage{0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; - wlr_box wholeMonitor = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; + CBox wholeMonitor = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; const auto POUTFB = blurMainFramebufferWithDamage(1, &fakeDamage); // render onto blurFB @@ -1197,7 +1188,7 @@ bool CHyprOpenGLImpl::shouldUseNewBlurOptimizations(SLayerSurface* pLayer, CWind return false; } -void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, float a, wlr_surface* pSurface, int round, bool blockBlurOptimization, float blurA) { +void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, float a, wlr_surface* pSurface, int round, bool blockBlurOptimization, float blurA) { RASSERT(m_RenderData.pMonitor, "Tried to render texture with blur without begin()!"); static auto* const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue; @@ -1251,7 +1242,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, m_RenderData.pCurrentMonData->primaryFB.bind(); // make a stencil for rounded corners to work with blur - scissor((wlr_box*)nullptr); // allow the entire window and stencil to render + scissor((CBox*)nullptr); // allow the entire window and stencil to render glClearStencil(0); glClear(GL_STENCIL_BUFFER_BIT); @@ -1271,7 +1262,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); // stencil done. Render everything. - wlr_box MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; + CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; // render our great blurred FB static auto* const PBLURIGNOREOPACITY = &g_pConfigManager->getConfigValuePtr("decoration:blur:ignore_opacity")->intValue; m_bEndFrame = true; // fix transformed @@ -1291,17 +1282,17 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, wlr_box* pBox, glStencilMask(-1); glStencilFunc(GL_ALWAYS, 1, 0xFF); - scissor((wlr_box*)nullptr); + scissor((CBox*)nullptr); } -void pushVert2D(float x, float y, float* arr, int& counter, wlr_box* box) { +void pushVert2D(float x, float y, float* arr, int& counter, CBox* box) { // 0-1 space god damnit arr[counter * 2 + 0] = x / box->width; arr[counter * 2 + 1] = y / box->height; counter++; } -void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad, int round, int borderSize, float a, int outerRound) { +void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, int round, int borderSize, float a, int outerRound) { RASSERT((box->width > 0 && box->height > 0), "Tried to render rect with width/height < 0!"); RASSERT(m_RenderData.pMonitor, "Tried to render rect without begin()!"); @@ -1310,10 +1301,8 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad, if (m_RenderData.damage.empty() || (m_pCurrentWindow && m_pCurrentWindow->m_sAdditionalConfigData.forceNoBorder)) return; - wlr_box newBox = *box; - scaleBox(&newBox, m_RenderData.renderModif.scale); - newBox.x += m_RenderData.renderModif.translate.x; - newBox.y += m_RenderData.renderModif.translate.y; + CBox newBox = *box; + newBox.scale(m_RenderData.renderModif.scale).translate(m_RenderData.renderModif.translate); box = &newBox; @@ -1331,7 +1320,7 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad, round += round == 0 ? 0 : scaledBorderSize; float matrix[9]; - wlr_matrix_project_box(matrix, box, wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, + wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here float glMatrix[9]; @@ -1356,9 +1345,9 @@ void CHyprOpenGLImpl::renderBorder(wlr_box* box, const CGradientValueData& grad, glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.angle, (int)(grad.m_fAngle / (PI / 180.0)) % 360 * (PI / 180.0)); glUniform1f(m_RenderData.pCurrentMonData->m_shBORDER1.alpha, a); - wlr_box transformedBox; - wlr_box_transform(&transformedBox, box, wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, - m_RenderData.pMonitor->vecTransformedSize.y); + CBox transformedBox = *box; + transformedBox.transform(wlr_output_transform_invert(m_RenderData.pMonitor->transform), m_RenderData.pMonitor->vecTransformedSize.x, + m_RenderData.pMonitor->vecTransformedSize.y); const auto TOPLEFT = Vector2D(transformedBox.x, transformedBox.y); const auto FULLSIZE = Vector2D(transformedBox.width, transformedBox.height); @@ -1587,7 +1576,7 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) { const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); - wlr_box windowBox; + CBox windowBox; // some mafs to figure out the correct box // the originalClosedPos is relative to the monitor's pos Vector2D scaleXY = Vector2D((PMONITOR->scale * PWINDOW->m_vRealSize.vec().x / (PWINDOW->m_vOriginalClosedSize.x * PMONITOR->scale)), @@ -1601,7 +1590,7 @@ void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) { CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; if (*PDIMAROUND && (*pWindow)->m_sAdditionalConfigData.dimAround) { - wlr_box monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y}; + CBox monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y}; g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * PWINDOW->m_fAlpha.fl())); g_pHyprRenderer->damageMonitor(PMONITOR); } @@ -1629,7 +1618,7 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) { const auto PMONITOR = g_pCompositor->getMonitorFromID(PLAYER->monitorID); - wlr_box monbox = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; + CBox monbox = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; CRegion fakeDamage{0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y}; @@ -1640,7 +1629,7 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) { m_bEndFrame = false; } -void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, float a, CFramebuffer* matte) { +void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, float a, CFramebuffer* matte) { RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!"); RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!"); RASSERT(m_pCurrentWindow, "Tried to render shadow without a window!"); @@ -1650,10 +1639,8 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl TRACY_GPU_ZONE("RenderShadow"); - wlr_box newBox = *box; - scaleBox(&newBox, m_RenderData.renderModif.scale); - newBox.x += m_RenderData.renderModif.translate.x; - newBox.y += m_RenderData.renderModif.translate.y; + CBox newBox = *box; + newBox.scale(m_RenderData.renderModif.scale).translate(m_RenderData.renderModif.translate); box = &newBox; @@ -1665,7 +1652,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(wlr_box* box, int round, int range, fl const auto col = m_pCurrentWindow->m_cRealShadowColor.col(); float matrix[9]; - wlr_matrix_project_box(matrix, box, wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, + wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here float glMatrix[9]; @@ -1752,7 +1739,7 @@ void CHyprOpenGLImpl::saveBufferForMirror() { m_RenderData.pCurrentMonData->monitorMirrorFB.bind(); - wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y}; + CBox monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y}; blend(false); @@ -1764,7 +1751,7 @@ void CHyprOpenGLImpl::saveBufferForMirror() { } void CHyprOpenGLImpl::renderMirrored() { - wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y}; + CBox monbox = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y}; const auto PFB = &m_mMonitorRenderResources[m_RenderData.pMonitor->pMirrorOf].monitorMirrorFB; @@ -1867,7 +1854,7 @@ void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { origin.x = (m_RenderData.pMonitor->vecTransformedSize.x - PTEX->m_vSize.x * scale) / 2.0; } - wlr_box box = {origin.x, origin.y, PTEX->m_vSize.x * scale, PTEX->m_vSize.y * scale}; + CBox box = {origin.x, origin.y, PTEX->m_vSize.x * scale, PTEX->m_vSize.y * scale}; m_mMonitorRenderResources[pMonitor].backgroundTexBox = box; @@ -1954,7 +1941,7 @@ void CHyprOpenGLImpl::bindOffMain() { } void CHyprOpenGLImpl::renderOffToMain(CFramebuffer* off) { - wlr_box monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; + CBox monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; renderTexturePrimitive(off->m_cTex, &monbox); } diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index ab3eb7cf..93dccbf4 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -52,7 +52,7 @@ struct SMonitorRenderData { bool blurFBDirty = true; bool blurFBShouldRender = false; - wlr_box backgroundTexBox; + CBox backgroundTexBox; // Shaders bool m_bShadersInitialized = false; @@ -89,7 +89,7 @@ struct SCurrentRenderData { Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1); Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1); - wlr_box clipBox = {}; + CBox clipBox = {}; uint32_t discardMode = DISCARD_OPAQUE; float discardOpacity = 0.f; @@ -105,14 +105,14 @@ class CHyprOpenGLImpl { void end(); void bindWlrOutputFb(); - void renderRect(wlr_box*, const CColor&, int round = 0); - void renderRectWithBlur(wlr_box*, const CColor&, int round = 0, float blurA = 1.f); - void renderRectWithDamage(wlr_box*, const CColor&, CRegion* damage, int round = 0); - void renderTexture(wlr_texture*, wlr_box*, float a, int round = 0, bool allowCustomUV = false); - void renderTexture(const CTexture&, wlr_box*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); - void renderTextureWithBlur(const CTexture&, wlr_box*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); - void renderRoundedShadow(wlr_box*, int round, int range, float a = 1.0, CFramebuffer* matte = nullptr); - void renderBorder(wlr_box*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); + void renderRect(CBox*, const CColor&, int round = 0); + void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f); + void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0); + void renderTexture(wlr_texture*, CBox*, float a, int round = 0, bool allowCustomUV = false); + void renderTexture(const CTexture&, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); + void renderTextureWithBlur(const CTexture&, CBox*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); + void renderRoundedShadow(CBox*, int round, int range, float a = 1.0, CFramebuffer* matte = nullptr); + void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); void saveMatrix(); void setMatrixScaleTranslate(const Vector2D& translate, const float& scale); @@ -128,7 +128,7 @@ class CHyprOpenGLImpl { void clear(const CColor&); void clearWithTex(); - void scissor(const wlr_box*, bool transform = true); + void scissor(const CBox*, bool transform = true); void scissor(const pixman_box32*, bool transform = true); void scissor(const int x, const int y, const int w, const int h, bool transform = true); @@ -187,9 +187,9 @@ class CHyprOpenGLImpl { // returns the out FB, can be either Mirror or MirrorSwap CFramebuffer* blurMainFramebufferWithDamage(float a, CRegion* damage); - void renderTextureInternalWithDamage(const CTexture&, wlr_box* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false, + void renderTextureInternalWithDamage(const CTexture&, CBox* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowCustomUV = false, bool allowDim = false); - void renderTexturePrimitive(const CTexture& tex, wlr_box* pBox); + void renderTexturePrimitive(const CTexture& tex, CBox* pBox); void renderSplash(cairo_t* const, cairo_surface_t* const, double); void preBlurForCurrentMonitor(); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 82175b99..a43d6a2d 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -22,7 +22,7 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { double outputX = 0, outputY = 0; wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, RDATA->pMonitor->output, &outputX, &outputY); - wlr_box windowBox; + CBox windowBox; if (RDATA->surface && surface == RDATA->surface) { windowBox = {(int)outputX + RDATA->x + x, (int)outputY + RDATA->y + y, RDATA->w, RDATA->h}; @@ -67,7 +67,8 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { g_pHyprRenderer->calculateUVForSurface(RDATA->pWindow, surface, RDATA->squishOversized); - scaleBox(&windowBox, RDATA->pMonitor->scale); + windowBox.scale(RDATA->pMonitor->scale); + windowBox.round(); float rounding = RDATA->rounding; @@ -110,9 +111,9 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { } bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, CMonitor* pMonitor, CWorkspace* pWorkspace) { - wlr_box geometry = pWindow->getFullWindowBoundingBox(); + CBox geometry = pWindow->getFullWindowBoundingBox(); - if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, &geometry)) + if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, pMonitor->output, geometry.pWlr())) return false; if (pWindow->m_iWorkspaceID == -1) @@ -343,7 +344,14 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue; - SRenderData renderdata = {pMonitor, time, REALPOS.x, REALPOS.y}; + SRenderData renderdata = {pMonitor, time}; + CBox textureBox = {REALPOS.x, REALPOS.y, std::max(pWindow->m_vRealSize.vec().x, 5.0), std::max(pWindow->m_vRealSize.vec().y, 5.0)}; + + renderdata.x = textureBox.x; + renderdata.y = textureBox.y; + renderdata.w = textureBox.w; + renderdata.h = textureBox.h; + if (ignorePosition) { renderdata.x = pMonitor->vecPosition.x; renderdata.y = pMonitor->vecPosition.y; @@ -353,8 +361,6 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* decorate = false; renderdata.surface = pWindow->m_pWLSurface.wlr(); - renderdata.w = std::max(pWindow->m_vRealSize.vec().x, 5.0); // clamp the size to min 5, - renderdata.h = std::max(pWindow->m_vRealSize.vec().y, 5.0); // otherwise we'll have issues later with invalid boxes renderdata.dontRound = (pWindow->m_bIsFullscreen && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL) || (!pWindow->m_sSpecialRenderData.rounding); renderdata.fadeAlpha = pWindow->m_fAlpha.fl() * (pWindow->m_bPinned ? 1.f : PWORKSPACE->m_fAlpha.fl()); renderdata.alpha = pWindow->m_fActiveInactiveAlpha.fl(); @@ -377,7 +383,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* EMIT_HOOK_EVENT("render", RENDER_PRE_WINDOW); if (*PDIMAROUND && pWindow->m_sAdditionalConfigData.dimAround && !m_bRenderingSnapshot && mode != RENDER_PASS_POPUP) { - wlr_box monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.y}; + CBox monbox = {0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecTransformedSize.y}; g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMAROUND * renderdata.alpha * renderdata.fadeAlpha)); } @@ -446,8 +452,8 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall && renderdata.blur && *PBLUR) { - wlr_box wb = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h}; - scaleBox(&wb, pMonitor->scale); + CBox wb = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h}; + wb.scale(pMonitor->scale).round(); g_pHyprOpenGL->renderRectWithBlur(&wb, CColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1, renderdata.fadeAlpha); renderdata.blur = false; } @@ -466,9 +472,9 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* grad.m_fAngle = normalizeAngleRad(grad.m_fAngle); } - wlr_box windowBox = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h}; + CBox windowBox = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h}; - scaleBox(&windowBox, pMonitor->scale); + windowBox.scale(pMonitor->scale).round(); int borderSize = pWindow->m_sSpecialRenderData.borderSize.toUnderlying() == -1 ? *PBORDERSIZE : pWindow->m_sSpecialRenderData.borderSize.toUnderlying(); if (pWindow->m_sAdditionalConfigData.borderSize.toUnderlying() != -1) @@ -503,8 +509,9 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_POPUP) { if (!pWindow->m_bIsX11) { - wlr_box geom; - wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom); + CBox geom; + wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, geom.pWlr()); + geom.applyFromWlr(); renderdata.x -= geom.x; renderdata.y -= geom.y; @@ -604,7 +611,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* if (!g_pCompositor->m_sSeat.exclusiveClient && g_pSessionLockManager->isSessionLocked()) { // locked with no exclusive, draw only red - wlr_box boxe = {0, 0, INT16_MAX, INT16_MAX}; + CBox boxe = {0, 0, INT16_MAX, INT16_MAX}; g_pHyprOpenGL->renderRect(&boxe, CColor(1.0, 0.2, 0.2, 1.0)); return; } @@ -654,12 +661,12 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* const bool ANIMOUT = !pMonitor->specialWorkspaceID; if (*PDIMSPECIAL != 0.f) { - wlr_box monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale}; + CBox monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale}; g_pHyprOpenGL->renderRect(&monbox, CColor(0, 0, 0, *PDIMSPECIAL * (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS))); } if (*PBLURSPECIAL && *PBLUR) { - wlr_box monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale}; + CBox monbox = {translate.x, translate.y, pMonitor->vecTransformedSize.x * scale, pMonitor->vecTransformedSize.y * scale}; g_pHyprOpenGL->renderRectWithBlur(&monbox, CColor(0, 0, 0, 0), 0, (ANIMOUT ? (1.0 - SPECIALANIMPROGRS) : SPECIALANIMPROGRS)); } @@ -711,7 +718,7 @@ void CHyprRenderer::renderLockscreen(CMonitor* pMonitor, timespec* now) { if (!PSLS) { // locked with no surface, fill with red - wlr_box boxe = {0, 0, INT16_MAX, INT16_MAX}; + CBox boxe = {0, 0, INT16_MAX, INT16_MAX}; g_pHyprOpenGL->renderRect(&boxe, CColor(1.0, 0.2, 0.2, 1.0)); } else { renderSessionLockSurface(PSLS, pMonitor, now); @@ -753,8 +760,9 @@ void CHyprRenderer::calculateUVForSurface(CWindow* pWindow, wlr_surface* pSurfac if (!main || !pWindow) return; - wlr_box geom; - wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, &geom); + CBox geom; + wlr_xdg_surface_get_geometry(pWindow->m_uSurface.xdg, geom.pWlr()); + geom.applyFromWlr(); // ignore X and Y, adjust uv if (geom.x != 0 || geom.y != 0 || geom.width > pWindow->m_vRealSize.vec().x || geom.height > pWindow->m_vRealSize.vec().y) { @@ -1073,7 +1081,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } g_pHyprOpenGL->blend(true); - wlr_box renderBox = {0, 0, (int)pMonitor->vecPixelSize.x, (int)pMonitor->vecPixelSize.y}; + CBox renderBox = {0, 0, (int)pMonitor->vecPixelSize.x, (int)pMonitor->vecPixelSize.y}; renderWorkspace(pMonitor, g_pCompositor->getWorkspaceByID(pMonitor->activeWorkspace), &now, renderBox); renderLockscreen(pMonitor, &now); @@ -1091,7 +1099,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } if (*PDAMAGEBLINK && damageBlinkCleanup == 0) { - wlr_box monrect = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}; + CBox monrect = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}; g_pHyprOpenGL->renderRect(&monrect, CColor(1.0, 0.0, 1.0, 100.0 / 255.0), 0); damageBlinkCleanup = 1; } else if (*PDAMAGEBLINK) { @@ -1193,7 +1201,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { } } -void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const wlr_box& geometry) { +void CHyprRenderer::renderWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const CBox& geometry) { Vector2D translate = {geometry.x, geometry.y}; float scale = (float)geometry.width / pMonitor->vecPixelSize.x; @@ -1350,8 +1358,8 @@ void apply_exclusive(struct wlr_box* usable_area, uint32_t anchor, int32_t exclu } } -void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vector>& layerSurfaces, bool exclusiveZone, wlr_box* usableArea) { - wlr_box full_area = {pMonitor->vecPosition.x, pMonitor->vecPosition.y, pMonitor->vecSize.x, pMonitor->vecSize.y}; +void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vector>& layerSurfaces, bool exclusiveZone, CBox* usableArea) { + CBox full_area = {pMonitor->vecPosition.x, pMonitor->vecPosition.y, pMonitor->vecSize.x, pMonitor->vecSize.y}; for (auto& ls : layerSurfaces) { if (ls->fadingOut || ls->readyToDelete || !ls->layerSurface || ls->noProcess) @@ -1362,7 +1370,7 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vectorexclusive_zone > 0)) continue; - wlr_box bounds; + CBox bounds; if (PSTATE->exclusive_zone == -1) bounds = full_area; else @@ -1370,7 +1378,7 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vectorgeometry.width, ls->geometry.height}; - wlr_box box = {.width = PSTATE->desired_width, .height = PSTATE->desired_height}; + CBox box = {0, 0, PSTATE->desired_width, PSTATE->desired_height}; // Horizontal axis const uint32_t both_horiz = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; if (box.width == 0) { @@ -1425,7 +1433,9 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vectorgeometry = box; - apply_exclusive(usableArea, PSTATE->anchor, PSTATE->exclusive_zone, PSTATE->margin.top, PSTATE->margin.right, PSTATE->margin.bottom, PSTATE->margin.left); + apply_exclusive(usableArea->pWlr(), PSTATE->anchor, PSTATE->exclusive_zone, PSTATE->margin.top, PSTATE->margin.right, PSTATE->margin.bottom, PSTATE->margin.left); + + usableArea->applyFromWlr(); if (Vector2D{box.width, box.height} != OLDSIZE) wlr_layer_surface_v1_configure(ls->layerSurface, box.width, box.height); @@ -1445,7 +1455,7 @@ void CHyprRenderer::arrangeLayersForMonitor(const int& monitor) { PMONITOR->vecReservedBottomRight = Vector2D(); PMONITOR->vecReservedTopLeft = Vector2D(); - wlr_box usableArea = {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; + CBox usableArea = {PMONITOR->vecPosition.x, PMONITOR->vecPosition.y, PMONITOR->vecSize.x, PMONITOR->vecSize.y}; for (auto& la : PMONITOR->m_aLayerSurfaceLayers) arrangeLayerArray(PMONITOR, la, true, &usableArea); @@ -1529,10 +1539,10 @@ void CHyprRenderer::damageWindow(CWindow* pWindow) { if (g_pCompositor->m_bUnsafeState) return; - wlr_box damageBox = pWindow->getFullWindowBoundingBox(); + CBox damageBox = pWindow->getFullWindowBoundingBox(); for (auto& m : g_pCompositor->m_vMonitors) { - wlr_box fixedDamageBox = {damageBox.x - m->vecPosition.x, damageBox.y - m->vecPosition.y, damageBox.width, damageBox.height}; - scaleBox(&fixedDamageBox, m->scale); + CBox fixedDamageBox = {damageBox.x - m->vecPosition.x, damageBox.y - m->vecPosition.y, damageBox.width, damageBox.height}; + fixedDamageBox.scale(m->scale); m->addDamage(&fixedDamageBox); } @@ -1549,7 +1559,7 @@ void CHyprRenderer::damageMonitor(CMonitor* pMonitor) { if (g_pCompositor->m_bUnsafeState || pMonitor->isMirror()) return; - wlr_box damageBox = {0, 0, INT16_MAX, INT16_MAX}; + CBox damageBox = {0, 0, INT16_MAX, INT16_MAX}; pMonitor->addDamage(&damageBox); static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue; @@ -1558,7 +1568,7 @@ void CHyprRenderer::damageMonitor(CMonitor* pMonitor) { Debug::log(LOG, "Damage: Monitor {}", pMonitor->szName); } -void CHyprRenderer::damageBox(wlr_box* pBox) { +void CHyprRenderer::damageBox(CBox* pBox) { if (g_pCompositor->m_bUnsafeState) return; @@ -1566,8 +1576,8 @@ void CHyprRenderer::damageBox(wlr_box* pBox) { if (m->isMirror()) continue; // don't damage mirrors traditionally - wlr_box damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height}; - scaleBox(&damageBox, m->scale); + CBox damageBox = {pBox->x - m->vecPosition.x, pBox->y - m->vecPosition.y, pBox->width, pBox->height}; + damageBox.scale(m->scale); m->addDamage(&damageBox); } @@ -1578,7 +1588,7 @@ void CHyprRenderer::damageBox(wlr_box* pBox) { } void CHyprRenderer::damageBox(const int& x, const int& y, const int& w, const int& h) { - wlr_box box = {x, y, w, h}; + CBox box = {x, y, w, h}; damageBox(&box); } @@ -1611,8 +1621,8 @@ void CHyprRenderer::renderDragIcon(CMonitor* pMonitor, timespec* time) { wlr_surface_for_each_surface(g_pInputManager->m_sDrag.dragIcon->surface, renderSurface, &renderdata); - wlr_box box = {g_pInputManager->m_sDrag.pos.x - 2, g_pInputManager->m_sDrag.pos.y - 2, g_pInputManager->m_sDrag.dragIcon->surface->current.width + 4, - g_pInputManager->m_sDrag.dragIcon->surface->current.height + 4}; + CBox box = {g_pInputManager->m_sDrag.pos.x - 2, g_pInputManager->m_sDrag.pos.y - 2, g_pInputManager->m_sDrag.dragIcon->surface->current.width + 4, + g_pInputManager->m_sDrag.dragIcon->surface->current.height + 4}; g_pHyprRenderer->damageBox(&box); } @@ -1934,9 +1944,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->vecTransformedSize = Vector2D(x, y); if (pMonitor->createdByUser) { - wlr_box transformedBox = {0, 0, (int)pMonitor->vecTransformedSize.x, (int)pMonitor->vecTransformedSize.y}; - wlr_box_transform(&transformedBox, &transformedBox, wlr_output_transform_invert(pMonitor->output->transform), (int)pMonitor->vecTransformedSize.x, - (int)pMonitor->vecTransformedSize.y); + CBox transformedBox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}; + transformedBox.transform(wlr_output_transform_invert(pMonitor->output->transform), pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); pMonitor->vecPixelSize = Vector2D(transformedBox.width, transformedBox.height); } @@ -2092,9 +2101,9 @@ void CHyprRenderer::setOccludedForBackLayers(CRegion& region, CWorkspace* pWorks const Vector2D POS = w->m_vRealPosition.vec() + Vector2D{ROUNDING, ROUNDING} - PMONITOR->vecPosition + (w->m_bPinned ? Vector2D{} : pWorkspace->m_vRenderOffset.vec()); const Vector2D SIZE = w->m_vRealSize.vec() - Vector2D{ROUNDING * 2, ROUNDING * 2}; - wlr_box box = {POS.x, POS.y, SIZE.x, SIZE.y}; + CBox box = {POS.x, POS.y, SIZE.x, SIZE.y}; - scaleBox(&box, PMONITOR->scale); + box.scale(PMONITOR->scale); rg.add(&box); } diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 0281d33f..f28600b4 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -40,7 +40,7 @@ class CHyprRenderer { void arrangeLayersForMonitor(const int&); void damageSurface(wlr_surface*, double, double, double scale = 1.0); void damageWindow(CWindow*); - void damageBox(wlr_box*); + void damageBox(CBox*); void damageBox(const int& x, const int& y, const int& w, const int& h); void damageRegion(const CRegion&); void damageMonitor(CMonitor*); @@ -89,7 +89,7 @@ class CHyprRenderer { } m_sLastCursorData; private: - void arrangeLayerArray(CMonitor*, const std::vector>&, bool, wlr_box*); + void arrangeLayerArray(CMonitor*, const std::vector>&, bool, CBox*); void renderWorkspaceWindowsFullscreen(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) void renderWorkspaceWindows(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) void renderWindow(CWindow*, CMonitor*, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool ignoreAllGeometry = false); @@ -97,7 +97,7 @@ class CHyprRenderer { void renderSessionLockSurface(SSessionLockSurface*, CMonitor*, timespec*); void renderDragIcon(CMonitor*, timespec*); void renderIMEPopup(SIMEPopup*, CMonitor*, timespec*); - void renderWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const wlr_box& geometry); + void renderWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const CBox& geometry); void renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); bool m_bHasARenderedCursor = true; diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index c2edb9ce..422cd9b3 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -29,8 +29,8 @@ void CHyprDropShadowDecoration::damageEntire() { if (*PSHADOWS != 1) return; // disabled - wlr_box dm = {m_vLastWindowPos.x - m_seExtents.topLeft.x, m_vLastWindowPos.y - m_seExtents.topLeft.y, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x, - m_vLastWindowSize.y + m_seExtents.topLeft.y + m_seExtents.bottomRight.y}; + CBox dm = {m_vLastWindowPos.x - m_seExtents.topLeft.x, m_vLastWindowPos.y - m_seExtents.topLeft.y, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x, + m_vLastWindowSize.y + m_seExtents.topLeft.y + m_seExtents.bottomRight.y}; g_pHyprRenderer->damageBox(&dm); } @@ -68,9 +68,8 @@ void CHyprDropShadowDecoration::updateWindow(CWindow* pWindow) { maxExtents.bottomRight.y = EXTENTS.bottomRight.y; } - m_bLastWindowBox = {(int)(m_vLastWindowPos.x - maxExtents.topLeft.x - BORDER), (int)(m_vLastWindowPos.y - maxExtents.topLeft.y - BORDER), - (int)(m_vLastWindowSize.x + maxExtents.topLeft.x + maxExtents.bottomRight.x + 2 * BORDER), - (int)(m_vLastWindowSize.y + maxExtents.topLeft.y + maxExtents.bottomRight.y + 2 * BORDER)}; + m_bLastWindowBox = {m_vLastWindowPos.x, m_vLastWindowPos.y, m_vLastWindowSize.x, m_vLastWindowSize.y}; + m_eLastExtents = {{maxExtents.topLeft + Vector2D{BORDER, BORDER}}, {maxExtents.bottomRight + Vector2D{BORDER, BORDER}}}; } } @@ -103,55 +102,40 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D const auto ROUNDING = m_pWindow->rounding() + m_pWindow->getRealBorderSize(); // draw the shadow - wlr_box fullBox = {m_bLastWindowBox.x - *PSHADOWSIZE, m_bLastWindowBox.y - *PSHADOWSIZE, m_bLastWindowBox.width + 2.0 * *PSHADOWSIZE, - m_bLastWindowBox.height + 2.0 * *PSHADOWSIZE}; - - fullBox.x -= pMonitor->vecPosition.x; - fullBox.y -= pMonitor->vecPosition.y; + CBox fullBox = {m_bLastWindowBox.x, m_bLastWindowBox.y, m_bLastWindowBox.width, m_bLastWindowBox.height}; + fullBox.addExtents(m_eLastExtents).translate(-pMonitor->vecPosition); + fullBox.x -= *PSHADOWSIZE; + fullBox.y -= *PSHADOWSIZE; + fullBox.w += 2 * *PSHADOWSIZE; + fullBox.h += 2 * *PSHADOWSIZE; const float SHADOWSCALE = std::clamp(*PSHADOWSCALE, 0.f, 1.f); // scale the box in relation to the center of the box - const Vector2D NEWSIZE = Vector2D{fullBox.width, fullBox.height} * SHADOWSCALE; - fullBox.width = NEWSIZE.x; - fullBox.height = NEWSIZE.y; - - if (PSHADOWOFFSET->x < 0) { - fullBox.x += PSHADOWOFFSET->x; - } else if (PSHADOWOFFSET->x > 0) { - fullBox.x = m_bLastWindowBox.x + m_bLastWindowBox.width - fullBox.width + (SHADOWSCALE * *PSHADOWSIZE) + PSHADOWOFFSET->x - pMonitor->vecPosition.x; - } else { - fullBox.x += ((m_bLastWindowBox.width + 2.0 * *PSHADOWSIZE) - NEWSIZE.x) / 2.0; - } - - if (PSHADOWOFFSET->y < 0) { - fullBox.y += PSHADOWOFFSET->y; - } else if (PSHADOWOFFSET->y > 0) { - fullBox.y = m_bLastWindowBox.y + m_bLastWindowBox.height - fullBox.height + (SHADOWSCALE * *PSHADOWSIZE) + PSHADOWOFFSET->y - pMonitor->vecPosition.y; - } else { - fullBox.y += ((m_bLastWindowBox.height + 2.0 * *PSHADOWSIZE) - NEWSIZE.y) / 2.0; - } + fullBox.scaleFromCenter(SHADOWSCALE).translate(*PSHADOWOFFSET); m_seExtents = {{m_vLastWindowPos.x - fullBox.x - pMonitor->vecPosition.x + 2, m_vLastWindowPos.y - fullBox.y - pMonitor->vecPosition.y + 2}, {fullBox.x + fullBox.width + pMonitor->vecPosition.x - m_vLastWindowPos.x - m_vLastWindowSize.x + 2, fullBox.y + fullBox.height + pMonitor->vecPosition.y - m_vLastWindowPos.y - m_vLastWindowSize.y + 2}}; - fullBox.x += offset.x; - fullBox.y += offset.y; + fullBox.translate(offset); if (fullBox.width < 1 || fullBox.height < 1) return; // don't draw invisible shadows - g_pHyprOpenGL->scissor((wlr_box*)nullptr); + g_pHyprOpenGL->scissor((CBox*)nullptr); // we'll take the liberty of using this as it should not be used rn CFramebuffer& alphaFB = g_pHyprOpenGL->m_RenderData.pCurrentMonData->mirrorFB; auto* LASTFB = g_pHyprOpenGL->m_RenderData.currentFB; if (*PSHADOWIGNOREWINDOW) { - wlr_box windowBox = {m_bLastWindowBox.x - pMonitor->vecPosition.x, m_bLastWindowBox.y - pMonitor->vecPosition.y, m_bLastWindowBox.width, m_bLastWindowBox.height}; + CBox windowBox = m_bLastWindowBox; - scaleBox(&windowBox, pMonitor->scale); + windowBox.translate(-pMonitor->vecPosition).scale(pMonitor->scale); + windowBox.round(); + + windowBox.addExtents(SWindowDecorationExtents{m_eLastExtents * pMonitor->scale}.floor()).round(); if (windowBox.width < 1 || windowBox.height < 1) { return; // prevent assert failed @@ -165,7 +149,7 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D LASTFB->bind(); } - scaleBox(&fullBox, pMonitor->scale); + fullBox.scale(pMonitor->scale).round(); g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a, &alphaFB); } diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index 7fadf851..d7ec043e 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -27,5 +27,6 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { Vector2D m_vLastWindowPos; Vector2D m_vLastWindowSize; - wlr_box m_bLastWindowBox = {0}; + CBox m_bLastWindowBox = {0}; + SWindowDecorationExtents m_eLastExtents = {}; }; \ No newline at end of file diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index a34a47b7..df269bce 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -76,8 +76,8 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) { } void CHyprGroupBarDecoration::damageEntire() { - wlr_box dm = {m_vLastWindowPos.x - m_seExtents.topLeft.x, m_vLastWindowPos.y - m_seExtents.topLeft.y, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x, - m_seExtents.topLeft.y}; + CBox dm = {m_vLastWindowPos.x - m_seExtents.topLeft.x, m_vLastWindowPos.y - m_seExtents.topLeft.y, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x, + m_seExtents.topLeft.y}; g_pHyprRenderer->damageBox(&dm); } @@ -99,13 +99,13 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& int xoff = 0; for (int i = 0; i < barsToDraw; ++i) { - wlr_box rect = {m_vLastWindowPos.x + xoff - pMonitor->vecPosition.x + offset.x, - m_vLastWindowPos.y - BAR_PADDING_OUTER_VERT - BORDERSIZE - BAR_INDICATOR_HEIGHT - pMonitor->vecPosition.y + offset.y, m_fBarWidth, BAR_INDICATOR_HEIGHT}; + CBox rect = {m_vLastWindowPos.x + xoff - pMonitor->vecPosition.x + offset.x, + m_vLastWindowPos.y - BAR_PADDING_OUTER_VERT - BORDERSIZE - BAR_INDICATOR_HEIGHT - pMonitor->vecPosition.y + offset.y, m_fBarWidth, BAR_INDICATOR_HEIGHT}; if (rect.width <= 0 || rect.height <= 0) break; - scaleBox(&rect, pMonitor->scale); + rect.scale(pMonitor->scale); static auto* const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.active")->data; static auto* const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.inactive")->data; diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp index 29d50595..47945b38 100644 --- a/src/render/decorations/IHyprWindowDecoration.hpp +++ b/src/render/decorations/IHyprWindowDecoration.hpp @@ -11,11 +11,6 @@ enum eDecorationType DECORATION_CUSTOM }; -struct SWindowDecorationExtents { - Vector2D topLeft; - Vector2D bottomRight; -}; - enum eDecorationLayer { DECORATION_LAYER_BOTTOM = 0, /* lowest. */ From 447c173cad9c4dbc0a7f48b2efcf2bd190eb6c53 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 4 Nov 2023 17:04:10 +0000 Subject: [PATCH 168/513] includes: include sharedDefs in includes.hpp --- src/includes.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/includes.hpp b/src/includes.hpp index 2ffb7710..b6f357bf 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -146,3 +146,4 @@ extern "C" { #include "helpers/Vector2D.hpp" #include "helpers/Box.hpp" +#include "SharedDefs.hpp" From 32b3d2b4560b4a5c986a564ae2220312c22fcafd Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 4 Nov 2023 17:27:21 +0000 Subject: [PATCH 169/513] includes: include vector2d for sharedDefs --- src/SharedDefs.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/SharedDefs.hpp b/src/SharedDefs.hpp index c060ac26..fb99caaa 100644 --- a/src/SharedDefs.hpp +++ b/src/SharedDefs.hpp @@ -1,5 +1,7 @@ #pragma once +#include "helpers/Vector2D.hpp" + enum eIcons { ICON_WARNING = 0, From a3e20d2d5f32f5d6e489bd5fa83a8fb6d0da77af Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 4 Nov 2023 17:39:56 +0000 Subject: [PATCH 170/513] wlsurface: fix small detection --- src/helpers/WLSurface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/WLSurface.cpp b/src/helpers/WLSurface.cpp index 33109b94..256c89b8 100644 --- a/src/helpers/WLSurface.cpp +++ b/src/helpers/WLSurface.cpp @@ -31,7 +31,7 @@ bool CWLSurface::small() const { if (!m_pOwner || !exists()) return false; - return std::abs(m_pOwner->m_vReportedSize.x - m_pWLRSurface->current.buffer_width) > 1 || std::abs(m_pOwner->m_vReportedSize.y - m_pWLRSurface->current.buffer_height) > 1; + 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 { From 7a09d24065050ad5b9490a6be947229ae83cb824 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 4 Nov 2023 17:45:31 +0000 Subject: [PATCH 171/513] shadow: fix ignore_window false --- src/render/decorations/CHyprDropShadowDecoration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 422cd9b3..38feb512 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -150,7 +150,7 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D } fullBox.scale(pMonitor->scale).round(); - g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a, &alphaFB); + g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a, *PSHADOWIGNOREWINDOW ? &alphaFB : nullptr); } eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() { From 64a084477ea8df67cbb35b22826a1f6a0845e123 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 4 Nov 2023 19:32:50 +0000 Subject: [PATCH 172/513] shadows: fix on transformed --- src/render/OpenGL.cpp | 95 ++++++++++++++----- src/render/OpenGL.hpp | 6 +- .../decorations/CHyprDropShadowDecoration.cpp | 22 +++-- src/render/shaders/Textures.hpp | 10 ++ 4 files changed, 101 insertions(+), 32 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 0011e636..8c691b35 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -235,8 +235,10 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shRGBA.program = prog; m_RenderData.pCurrentMonData->m_shRGBA.proj = glGetUniformLocation(prog, "proj"); m_RenderData.pCurrentMonData->m_shRGBA.tex = glGetUniformLocation(prog, "tex"); + m_RenderData.pCurrentMonData->m_shRGBA.alphaMatte = glGetUniformLocation(prog, "texMatte"); m_RenderData.pCurrentMonData->m_shRGBA.alpha = glGetUniformLocation(prog, "alpha"); m_RenderData.pCurrentMonData->m_shRGBA.texAttrib = glGetAttribLocation(prog, "texcoord"); + m_RenderData.pCurrentMonData->m_shRGBA.matteTexAttrib = glGetAttribLocation(prog, "texcoordMatte"); m_RenderData.pCurrentMonData->m_shRGBA.posAttrib = glGetAttribLocation(prog, "pos"); m_RenderData.pCurrentMonData->m_shRGBA.discardOpaque = glGetUniformLocation(prog, "discardOpaque"); m_RenderData.pCurrentMonData->m_shRGBA.discardAlpha = glGetUniformLocation(prog, "discardAlpha"); @@ -246,6 +248,7 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shRGBA.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shRGBA.applyTint = glGetUniformLocation(prog, "applyTint"); m_RenderData.pCurrentMonData->m_shRGBA.tint = glGetUniformLocation(prog, "tint"); + m_RenderData.pCurrentMonData->m_shRGBA.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte"); prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBAPASSTHRU); m_RenderData.pCurrentMonData->m_shPASSTHRURGBA.program = prog; @@ -254,6 +257,14 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shPASSTHRURGBA.texAttrib = glGetAttribLocation(prog, "texcoord"); m_RenderData.pCurrentMonData->m_shPASSTHRURGBA.posAttrib = glGetAttribLocation(prog, "pos"); + prog = createProgram(TEXVERTSRC, TEXFRAGSRCRGBAMATTE); + m_RenderData.pCurrentMonData->m_shMATTE.program = prog; + m_RenderData.pCurrentMonData->m_shMATTE.proj = glGetUniformLocation(prog, "proj"); + m_RenderData.pCurrentMonData->m_shMATTE.tex = glGetUniformLocation(prog, "tex"); + m_RenderData.pCurrentMonData->m_shMATTE.alphaMatte = glGetUniformLocation(prog, "texMatte"); + m_RenderData.pCurrentMonData->m_shMATTE.texAttrib = glGetAttribLocation(prog, "texcoord"); + m_RenderData.pCurrentMonData->m_shMATTE.posAttrib = glGetAttribLocation(prog, "pos"); + prog = createProgram(TEXVERTSRC, FRAGGLITCH); m_RenderData.pCurrentMonData->m_shGLITCH.program = prog; m_RenderData.pCurrentMonData->m_shGLITCH.proj = glGetUniformLocation(prog, "proj"); @@ -821,6 +832,64 @@ void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, CBox* pBox) { glBindTexture(tex.m_iTarget, 0); } +void CHyprOpenGLImpl::renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte) { + RASSERT(m_RenderData.pMonitor, "Tried to render texture without begin()!"); + RASSERT((tex.m_iTexID > 0), "Attempted to draw NULL texture!"); + + TRACY_GPU_ZONE("RenderTextureMatte"); + + if (m_RenderData.damage.empty()) + return; + + CBox newBox = *pBox; + newBox.scale(m_RenderData.renderModif.scale).translate(m_RenderData.renderModif.translate); + + // get transform + const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); + float matrix[9]; + wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix); + + float glMatrix[9]; + wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); + + CShader* shader = &m_RenderData.pCurrentMonData->m_shMATTE; + + glUseProgram(shader->program); + +#ifndef GLES2 + glUniformMatrix3fv(shader->proj, 1, GL_TRUE, glMatrix); +#else + wlr_matrix_transpose(glMatrix, glMatrix); + glUniformMatrix3fv(shader->proj, 1, GL_FALSE, glMatrix); +#endif + glUniform1i(shader->tex, 0); + glUniform1i(shader->alphaMatte, 1); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(tex.m_iTarget, tex.m_iTexID); + + glActiveTexture(GL_TEXTURE0 + 1); + glBindTexture(matte.m_cTex.m_iTarget, matte.m_cTex.m_iTexID); + + glVertexAttribPointer(shader->posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); + glVertexAttribPointer(shader->texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); + + glEnableVertexAttribArray(shader->posAttrib); + glEnableVertexAttribArray(shader->texAttrib); + + for (auto& RECT : m_RenderData.damage.getRects()) { + scissor(&RECT); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + } + + scissor((CBox*)nullptr); + + glDisableVertexAttribArray(shader->posAttrib); + glDisableVertexAttribArray(shader->texAttrib); + + glBindTexture(tex.m_iTarget, 0); +} + // This probably isn't the fastest // but it works... well, I guess? // @@ -1629,7 +1698,7 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) { m_bEndFrame = false; } -void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, float a, CFramebuffer* matte) { +void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, float a) { RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!"); RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!"); RASSERT(m_pCurrentWindow, "Tried to render shadow without a window!"); @@ -1647,7 +1716,6 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, float static auto* const PSHADOWPOWER = &g_pConfigManager->getConfigValuePtr("decoration:shadow_render_power")->intValue; const auto SHADOWPOWER = std::clamp((int)*PSHADOWPOWER, 1, 4); - const auto USEMATTE = matte; const auto col = m_pCurrentWindow->m_cRealShadowColor.col(); @@ -1682,33 +1750,11 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, float glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.range, range); glUniform1f(m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower, SHADOWPOWER); - if (USEMATTE) { - glUniform1i(m_RenderData.pCurrentMonData->m_shSHADOW.useAlphaMatte, 1); - glUniform1i(m_RenderData.pCurrentMonData->m_shSHADOW.alphaMatte, 0); - glActiveTexture(GL_TEXTURE0); - glBindTexture(matte->m_cTex.m_iTarget, matte->m_cTex.m_iTexID); - } else { - glUniform1i(m_RenderData.pCurrentMonData->m_shSHADOW.useAlphaMatte, 0); - } - - const float texVerts[] = { - ((float)(box->x + box->width) / m_RenderData.pMonitor->vecPixelSize.x), - ((float)box->y / m_RenderData.pMonitor->vecPixelSize.y), // top right - ((float)box->x / m_RenderData.pMonitor->vecPixelSize.x), - ((float)box->y / m_RenderData.pMonitor->vecPixelSize.y), // top left - ((float)(box->x + box->width) / m_RenderData.pMonitor->vecPixelSize.x), - ((float)(box->y + box->height) / m_RenderData.pMonitor->vecPixelSize.y), // bottom right - ((float)box->x / m_RenderData.pMonitor->vecPixelSize.x), - ((float)(box->y + box->height) / m_RenderData.pMonitor->vecPixelSize.y), // bottom left - }; - glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); - glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shSHADOW.matteTexAttrib, 2, GL_FLOAT, GL_FALSE, 0, texVerts); glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib); glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib); - glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.matteTexAttrib); if (m_RenderData.clipBox.width != 0 && m_RenderData.clipBox.height != 0) { CRegion damageClip{m_RenderData.clipBox.x, m_RenderData.clipBox.y, m_RenderData.clipBox.width, m_RenderData.clipBox.height}; @@ -1727,7 +1773,6 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, float } } - glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.matteTexAttrib); glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib); glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib); } diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 93dccbf4..fea967e5 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -59,6 +59,7 @@ struct SMonitorRenderData { CShader m_shQUAD; CShader m_shRGBA; CShader m_shPASSTHRURGBA; + CShader m_shMATTE; CShader m_shRGBX; CShader m_shEXT; CShader m_shBLUR1; @@ -96,6 +97,7 @@ struct SCurrentRenderData { }; class CGradientValueData; +class CHyprDropShadowDecoration; class CHyprOpenGLImpl { public: @@ -111,7 +113,7 @@ class CHyprOpenGLImpl { void renderTexture(wlr_texture*, CBox*, float a, int round = 0, bool allowCustomUV = false); void renderTexture(const CTexture&, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); void renderTextureWithBlur(const CTexture&, CBox*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); - void renderRoundedShadow(CBox*, int round, int range, float a = 1.0, CFramebuffer* matte = nullptr); + void renderRoundedShadow(CBox*, int round, int range, float a = 1.0); void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); void saveMatrix(); @@ -190,6 +192,7 @@ class CHyprOpenGLImpl { void renderTextureInternalWithDamage(const CTexture&, CBox* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowCustomUV = false, bool allowDim = false); void renderTexturePrimitive(const CTexture& tex, CBox* pBox); + void renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte); void renderSplash(cairo_t* const, cairo_surface_t* const, double); void preBlurForCurrentMonitor(); @@ -197,6 +200,7 @@ class CHyprOpenGLImpl { bool shouldUseNewBlurOptimizations(SLayerSurface* pLayer, CWindow* pWindow); friend class CHyprRenderer; + friend class CHyprDropShadowDecoration; }; inline std::unique_ptr g_pHyprOpenGL; diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 38feb512..74f14e0c 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -126,8 +126,9 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D g_pHyprOpenGL->scissor((CBox*)nullptr); // we'll take the liberty of using this as it should not be used rn - CFramebuffer& alphaFB = g_pHyprOpenGL->m_RenderData.pCurrentMonData->mirrorFB; - auto* LASTFB = g_pHyprOpenGL->m_RenderData.currentFB; + CFramebuffer& alphaFB = g_pHyprOpenGL->m_RenderData.pCurrentMonData->mirrorFB; + CFramebuffer& alphaSwapFB = g_pHyprOpenGL->m_RenderData.pCurrentMonData->mirrorSwapFB; + auto* LASTFB = g_pHyprOpenGL->m_RenderData.currentFB; if (*PSHADOWIGNOREWINDOW) { CBox windowBox = m_bLastWindowBox; @@ -146,11 +147,20 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D g_pHyprOpenGL->renderRect(&windowBox, CColor(1.0, 1.0, 1.0, 1.0), ROUNDING * pMonitor->scale); - LASTFB->bind(); - } + alphaSwapFB.bind(); + g_pHyprOpenGL->clear(CColor(0, 0, 0, 0)); - fullBox.scale(pMonitor->scale).round(); - g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a, *PSHADOWIGNOREWINDOW ? &alphaFB : nullptr); + g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a); + + LASTFB->bind(); + + CBox monbox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}; + g_pHyprOpenGL->m_bEndFrame = true; + g_pHyprOpenGL->renderTextureMatte(alphaSwapFB.m_cTex, &monbox, alphaFB); + g_pHyprOpenGL->m_bEndFrame = false; + } else { + g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a); + } } eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() { diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index 6f19ac9f..cf753bb4 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -130,6 +130,16 @@ void main() { gl_FragColor = texture2D(tex, v_texcoord); })#"; +inline const std::string TEXFRAGSRCRGBAMATTE = R"#( +precision mediump float; +varying vec2 v_texcoord; // is in 0-1 +uniform sampler2D tex; +uniform sampler2D texMatte; + +void main() { + gl_FragColor = texture2D(tex, v_texcoord) * (1.0 - texture2D(texMatte, v_texcoord)[3]); +})#"; + inline const std::string TEXFRAGSRCRGBX = R"#( precision mediump float; varying vec2 v_texcoord; From 66a3719b8613a69890f7e6cb0ebdb107703e42e0 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 4 Nov 2023 19:35:49 +0000 Subject: [PATCH 173/513] renderer: allow transform enabling from outside opengl --- src/render/OpenGL.cpp | 4 ++++ src/render/OpenGL.hpp | 6 +++--- src/render/decorations/CHyprDropShadowDecoration.cpp | 6 +++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 8c691b35..b8028c3f 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1994,3 +1994,7 @@ void CHyprOpenGLImpl::bindBackOnMain() { m_RenderData.pCurrentMonData->primaryFB.bind(); m_RenderData.currentFB = &m_RenderData.pCurrentMonData->primaryFB; } + +void CHyprOpenGLImpl::setMonitorTransformEnabled(bool enabled) { + m_bEndFrame = !enabled; +} diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index fea967e5..7e3e4e7c 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -97,7 +97,6 @@ struct SCurrentRenderData { }; class CGradientValueData; -class CHyprDropShadowDecoration; class CHyprOpenGLImpl { public: @@ -115,6 +114,9 @@ class CHyprOpenGLImpl { void renderTextureWithBlur(const CTexture&, CBox*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); void renderRoundedShadow(CBox*, int round, int range, float a = 1.0); void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); + void renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte); + + void setMonitorTransformEnabled(bool enabled); void saveMatrix(); void setMatrixScaleTranslate(const Vector2D& translate, const float& scale); @@ -192,7 +194,6 @@ class CHyprOpenGLImpl { void renderTextureInternalWithDamage(const CTexture&, CBox* pBox, float a, CRegion* damage, int round = 0, bool discardOpaque = false, bool noAA = false, bool allowCustomUV = false, bool allowDim = false); void renderTexturePrimitive(const CTexture& tex, CBox* pBox); - void renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte); void renderSplash(cairo_t* const, cairo_surface_t* const, double); void preBlurForCurrentMonitor(); @@ -200,7 +201,6 @@ class CHyprOpenGLImpl { bool shouldUseNewBlurOptimizations(SLayerSurface* pLayer, CWindow* pWindow); friend class CHyprRenderer; - friend class CHyprDropShadowDecoration; }; inline std::unique_ptr g_pHyprOpenGL; diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 74f14e0c..eb1ed8ca 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -154,10 +154,10 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D LASTFB->bind(); - CBox monbox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}; - g_pHyprOpenGL->m_bEndFrame = true; + CBox monbox = {0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}; + g_pHyprOpenGL->setMonitorTransformEnabled(false); g_pHyprOpenGL->renderTextureMatte(alphaSwapFB.m_cTex, &monbox, alphaFB); - g_pHyprOpenGL->m_bEndFrame = false; + g_pHyprOpenGL->setMonitorTransformEnabled(true); } else { g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a); } From 2b07d54bc74f34a3561612bedaa44ad8ab550b8b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 4 Nov 2023 20:11:22 +0000 Subject: [PATCH 174/513] shadow: fix missed fullBox.scale --- src/render/decorations/CHyprDropShadowDecoration.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index eb1ed8ca..5341dec9 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -130,6 +130,8 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D CFramebuffer& alphaSwapFB = g_pHyprOpenGL->m_RenderData.pCurrentMonData->mirrorSwapFB; auto* LASTFB = g_pHyprOpenGL->m_RenderData.currentFB; + fullBox.scale(pMonitor->scale).round(); + if (*PSHADOWIGNOREWINDOW) { CBox windowBox = m_bLastWindowBox; From 74cf2281dd38a533916eb0b201c3128423b94d7c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 4 Nov 2023 21:03:08 +0000 Subject: [PATCH 175/513] binds: add movefocus_cycles_fullscreen fixes #3738 --- src/Compositor.cpp | 16 +++++++++++----- src/config/ConfigManager.cpp | 15 ++++++++------- src/managers/KeybindManager.cpp | 5 +++-- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 53cd2e83..74ac7c11 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1504,13 +1504,19 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) { // 0 -> history, 1 -> shared length static auto* const PMETHOD = &g_pConfigManager->getConfigValuePtr("binds:focus_preferred_method")->intValue; - const auto WINDOWIDEALBB = pWindow->getWindowIdealBoundingBoxIgnoreReserved(); + const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); - const auto POSA = Vector2D(WINDOWIDEALBB.x, WINDOWIDEALBB.y); - const auto SIZEA = Vector2D(WINDOWIDEALBB.width, WINDOWIDEALBB.height); + if (!PMONITOR) + return nullptr; // ?? - auto leaderValue = -1; - CWindow* leaderWindow = nullptr; + const auto WINDOWIDEALBB = pWindow->m_bIsFullscreen ? wlr_box{(int)PMONITOR->vecPosition.x, (int)PMONITOR->vecPosition.y, (int)PMONITOR->vecSize.x, (int)PMONITOR->vecSize.y} : + pWindow->getWindowIdealBoundingBoxIgnoreReserved(); + + const auto POSA = Vector2D(WINDOWIDEALBB.x, WINDOWIDEALBB.y); + const auto SIZEA = Vector2D(WINDOWIDEALBB.width, WINDOWIDEALBB.height); + + auto leaderValue = -1; + CWindow* leaderWindow = nullptr; for (auto& w : m_vWindows) { if (w.get() == pWindow || !w->m_bIsMapped || w->isHidden() || w->m_bIsFloating || !isWorkspaceVisible(w->m_iWorkspaceID)) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index e016ba75..f5b9416b 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -243,13 +243,14 @@ void CConfigManager::setDefaultVars() { configValues["input:tablet:region_position"].vecValue = Vector2D(); configValues["input:tablet:region_size"].vecValue = Vector2D(); - configValues["binds:pass_mouse_when_bound"].intValue = 0; - configValues["binds:scroll_event_delay"].intValue = 300; - configValues["binds:workspace_back_and_forth"].intValue = 0; - configValues["binds:allow_workspace_cycles"].intValue = 0; - configValues["binds:workspace_center_on"].intValue = 1; - configValues["binds:focus_preferred_method"].intValue = 0; - configValues["binds:ignore_group_lock"].intValue = 0; + configValues["binds:pass_mouse_when_bound"].intValue = 0; + configValues["binds:scroll_event_delay"].intValue = 300; + configValues["binds:workspace_back_and_forth"].intValue = 0; + configValues["binds:allow_workspace_cycles"].intValue = 0; + configValues["binds:workspace_center_on"].intValue = 1; + configValues["binds:focus_preferred_method"].intValue = 0; + configValues["binds:ignore_group_lock"].intValue = 0; + configValues["binds:movefocus_cycles_fullscreen"].intValue = 1; configValues["gestures:workspace_swipe"].intValue = 0; configValues["gestures:workspace_swipe_fingers"].intValue = 3; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index ac995ad9..3bed027d 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1004,7 +1004,8 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { } void CKeybindManager::moveFocusTo(std::string args) { - char arg = args[0]; + static auto* const PFULLCYCLE = &g_pConfigManager->getConfigValuePtr("binds:movefocus_cycles_fullscreen")->intValue; + char arg = args[0]; if (!isDirection(args)) { Debug::log(ERR, "Cannot move focus in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg); @@ -1020,7 +1021,7 @@ void CKeybindManager::moveFocusTo(std::string args) { // remove constraints g_pInputManager->unconstrainMouse(); - const auto PWINDOWTOCHANGETO = PLASTWINDOW->m_bIsFullscreen ? + const auto PWINDOWTOCHANGETO = *PFULLCYCLE && PLASTWINDOW->m_bIsFullscreen ? (arg == 'd' || arg == 'b' || arg == 'r' ? g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true) : g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW, true)) : g_pCompositor->getWindowInDirection(PLASTWINDOW, arg); From 931927de29256a46004cd6f71fdf45ed76470b73 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 4 Nov 2023 21:45:34 +0000 Subject: [PATCH 176/513] dwindle: move to CBox for expressing nodes --- src/helpers/Box.cpp | 10 ++- src/helpers/Box.hpp | 14 ++++ src/layout/DwindleLayout.cpp | 150 ++++++++++++++++------------------- src/layout/DwindleLayout.hpp | 9 +-- 4 files changed, 94 insertions(+), 89 deletions(-) diff --git a/src/helpers/Box.cpp b/src/helpers/Box.cpp index 450871cb..e71ed622 100644 --- a/src/helpers/Box.cpp +++ b/src/helpers/Box.cpp @@ -101,4 +101,12 @@ CBox CBox::roundInternal() { float newH = y + h - std::floor(y); return CBox{std::floor(x), std::floor(y), std::floor(newW), std::floor(newH)}; -} \ No newline at end of file +} + +Vector2D CBox::pos() const { + return {x, y}; +} + +Vector2D CBox::size() const { + return {w, h}; +} diff --git a/src/helpers/Box.hpp b/src/helpers/Box.hpp index 7a8aa939..a5f24d7b 100644 --- a/src/helpers/Box.hpp +++ b/src/helpers/Box.hpp @@ -32,6 +32,13 @@ class CBox { h = d; } + CBox(const Vector2D& pos, const Vector2D& size) { + x = pos.x; + y = pos.y; + w = size.x; + h = size.y; + } + wlr_box wlr(); wlr_box* pWlr(); @@ -45,6 +52,8 @@ class CBox { CBox& addExtents(const SWindowDecorationExtents& e); Vector2D middle() const; + Vector2D pos() const; + Vector2D size() const; bool containsPoint(const Vector2D& vec) const; bool empty() const; @@ -59,6 +68,11 @@ class CBox { double height; }; + // + bool operator==(const CBox& rhs) const { + return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h; + } + private: CBox roundInternal(); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 45db3855..2eb428ab 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -9,7 +9,7 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverrid static auto* const PFLMULT = &g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier")->floatValue; if (*PPRESERVESPLIT == 0 && *PSMARTSPLIT == 0) { - splitTop = size.y * *PFLMULT > size.x; + splitTop = box.h * *PFLMULT > box.w; } if (verticalOverride == true) @@ -21,18 +21,14 @@ void SDwindleNodeData::recalcSizePosRecursive(bool force, bool horizontalOverrid if (SPLITSIDE) { // split left/right - int const FIRSTSIZE = std::round(size.x / 2 * splitRatio); - children[0]->position = position; - children[0]->size = Vector2D(FIRSTSIZE, size.y); - children[1]->position = Vector2D(position.x + FIRSTSIZE, position.y); - children[1]->size = Vector2D(size.x - FIRSTSIZE, size.y); + const float FIRSTSIZE = box.w / 2.0 * splitRatio; + children[0]->box = CBox{box.x, box.y, FIRSTSIZE, box.h}; + children[1]->box = CBox{box.x + FIRSTSIZE, box.y, box.w - FIRSTSIZE, box.h}; } else { // split top/bottom - int const FIRSTSIZE = std::round(size.y / 2 * splitRatio); - children[0]->position = position; - children[0]->size = Vector2D(size.x, FIRSTSIZE); - children[1]->position = Vector2D(position.x, position.y + FIRSTSIZE); - children[1]->size = Vector2D(size.x, size.y - FIRSTSIZE); + const float FIRSTSIZE = box.h / 2.0 * splitRatio; + children[0]->box = CBox{box.x, box.y, box.w, FIRSTSIZE}; + children[1]->box = CBox{box.x, box.y + FIRSTSIZE, box.w, box.h - FIRSTSIZE}; } children[0]->recalcSizePosRecursive(force); @@ -109,10 +105,10 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for } // for gaps outer - const bool DISPLAYLEFT = STICKS(pNode->position.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x); - const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x); - const bool DISPLAYTOP = STICKS(pNode->position.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y); - const bool DISPLAYBOTTOM = STICKS(pNode->position.y + pNode->size.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y); + const bool DISPLAYLEFT = STICKS(pNode->box.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x); + const bool DISPLAYRIGHT = STICKS(pNode->box.x + pNode->box.w, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x); + const bool DISPLAYTOP = STICKS(pNode->box.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y); + const bool DISPLAYBOTTOM = STICKS(pNode->box.y + pNode->box.h, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y); const auto PWINDOW = pNode->pWindow; // get specific gaps and rules for this workspace, @@ -137,8 +133,11 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for return; } - PWINDOW->m_vSize = pNode->size; - PWINDOW->m_vPosition = pNode->position; + CBox nodeBox = pNode->box; + nodeBox.round(); + + PWINDOW->m_vSize = nodeBox.size(); + PWINDOW->m_vPosition = nodeBox.pos(); const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->m_iWorkspaceID); @@ -284,7 +283,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire } // first, check if OPENINGON isn't too big. - const auto PREDSIZEMAX = OPENINGON ? Vector2D(OPENINGON->size.x, OPENINGON->size.y) : PMONITOR->vecSize; + const auto PREDSIZEMAX = OPENINGON ? Vector2D(OPENINGON->box.w, OPENINGON->box.h) : PMONITOR->vecSize; if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); MAXSIZE.x < PREDSIZEMAX.x || MAXSIZE.y < PREDSIZEMAX.y) { // we can't continue. make it floating. pWindow->m_bIsFloating = true; @@ -305,8 +304,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire // if it's the first, it's easy. Make it fullscreen. if (!OPENINGON || OPENINGON->pWindow == pWindow) { - PNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; - PNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight; + PNODE->box = CBox{PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft, PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight}; applyNodeDataToWindow(PNODE); @@ -353,8 +351,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire const auto NEWPARENT = &m_lDwindleNodesData.back(); // make the parent have the OPENINGON's stats - NEWPARENT->position = OPENINGON->position; - NEWPARENT->size = OPENINGON->size; + NEWPARENT->box = OPENINGON->box; NEWPARENT->workspaceID = OPENINGON->workspaceID; NEWPARENT->pParent = OPENINGON->pParent; NEWPARENT->isNode = true; // it is a node @@ -363,7 +360,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire const auto PWIDTHMULTIPLIER = &g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier")->floatValue; // if cursor over first child, make it first, etc - const auto SIDEBYSIDE = NEWPARENT->size.x > NEWPARENT->size.y * *PWIDTHMULTIPLIER; + const auto SIDEBYSIDE = NEWPARENT->box.w > NEWPARENT->box.h * *PWIDTHMULTIPLIER; NEWPARENT->splitTop = !SIDEBYSIDE; static auto* const PFORCESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:force_split")->intValue; @@ -395,11 +392,11 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire if (*PERMANENTDIRECTIONOVERRIDE == 0) overrideDirection = DIRECTION_DEFAULT; } else if (*PSMARTSPLIT == 1) { - const auto tl = NEWPARENT->position; - const auto tr = NEWPARENT->position + Vector2D(NEWPARENT->size.x, 0); - const auto bl = NEWPARENT->position + Vector2D(0, NEWPARENT->size.y); - const auto br = NEWPARENT->position + NEWPARENT->size; - const auto cc = NEWPARENT->position + NEWPARENT->size / 2; + const auto tl = NEWPARENT->box.pos(); + const auto tr = NEWPARENT->box.pos() + Vector2D(NEWPARENT->box.w, 0); + const auto bl = NEWPARENT->box.pos() + Vector2D(0, NEWPARENT->box.h); + const auto br = NEWPARENT->box.pos() + NEWPARENT->box.size(); + const auto cc = NEWPARENT->box.pos() + NEWPARENT->box.size() / 2; if (MOUSECOORDS.inTriangle(tl, tr, cc)) { NEWPARENT->splitTop = true; @@ -420,11 +417,9 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire } } else if (*PFORCESPLIT == 0 || !pWindow->m_bFirstMap) { if ((SIDEBYSIDE && - VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / *PWIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x / 2.f, - NEWPARENT->position.y + NEWPARENT->size.y)) || + VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y + NEWPARENT->box.h)) || (!SIDEBYSIDE && - VECINRECT(MOUSECOORDS, NEWPARENT->position.x, NEWPARENT->position.y / *PWIDTHMULTIPLIER, NEWPARENT->position.x + NEWPARENT->size.x, - NEWPARENT->position.y + NEWPARENT->size.y / 2.f))) { + VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w, NEWPARENT->box.y + NEWPARENT->box.h / 2.f))) { // we are hovering over the first node, make PNODE first. NEWPARENT->children[1] = OPENINGON; NEWPARENT->children[0] = PNODE; @@ -453,18 +448,14 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire } // Update the children - if (!verticalOverride && (NEWPARENT->size.x * *PWIDTHMULTIPLIER > NEWPARENT->size.y || horizontalOverride)) { + if (!verticalOverride && (NEWPARENT->box.w * *PWIDTHMULTIPLIER > NEWPARENT->box.h || horizontalOverride)) { // split left/right -> forced - OPENINGON->position = NEWPARENT->position; - OPENINGON->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y); - PNODE->position = Vector2D(NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y); - PNODE->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y); + OPENINGON->box = {NEWPARENT->box.pos(), Vector2D(NEWPARENT->box.w / 2.f, NEWPARENT->box.h)}; + PNODE->box = {Vector2D(NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y), Vector2D(NEWPARENT->box.w / 2.f, NEWPARENT->box.h)}; } else { // split top/bottom - OPENINGON->position = NEWPARENT->position; - OPENINGON->size = Vector2D(NEWPARENT->size.x, NEWPARENT->size.y / 2.f); - PNODE->position = Vector2D(NEWPARENT->position.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f); - PNODE->size = Vector2D(NEWPARENT->size.x, NEWPARENT->size.y / 2.f); + OPENINGON->box = {NEWPARENT->box.pos(), Vector2D(NEWPARENT->box.w, NEWPARENT->box.h / 2.f)}; + PNODE->box = {Vector2D(NEWPARENT->box.x, NEWPARENT->box.y + NEWPARENT->box.h / 2.f), Vector2D(NEWPARENT->box.w, NEWPARENT->box.h / 2.f)}; } OPENINGON->pParent = NEWPARENT; @@ -501,9 +492,8 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) { const auto PSIBLING = PPARENT->children[0] == PNODE ? PPARENT->children[1] : PPARENT->children[0]; - PSIBLING->position = PPARENT->position; - PSIBLING->size = PPARENT->size; - PSIBLING->pParent = PPARENT->pParent; + PSIBLING->box = PPARENT->box; + PSIBLING->pParent = PPARENT->pParent; if (PPARENT->pParent != nullptr) { if (PPARENT->pParent->children[0] == PPARENT) { @@ -542,8 +532,7 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) { const auto TOPNODE = getMasterNodeOnWorkspace(PMONITOR->specialWorkspaceID); if (TOPNODE && PMONITOR) { - TOPNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; - TOPNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight; + TOPNODE->box = {PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft, PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight}; TOPNODE->recalcSizePosRecursive(); } } @@ -557,12 +546,11 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) { PFULLWINDOW->m_vRealSize = PMONITOR->vecSize; } else if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) { SDwindleNodeData fakeNode; - fakeNode.pWindow = PFULLWINDOW; - fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; - fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight; - fakeNode.workspaceID = PWORKSPACE->m_iID; - PFULLWINDOW->m_vPosition = fakeNode.position; - PFULLWINDOW->m_vSize = fakeNode.size; + fakeNode.pWindow = PFULLWINDOW; + fakeNode.box = {PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft, PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight}; + fakeNode.workspaceID = PWORKSPACE->m_iID; + PFULLWINDOW->m_vPosition = fakeNode.box.pos(); + PFULLWINDOW->m_vSize = fakeNode.box.size(); fakeNode.ignoreFullscreenChecks = true; applyNodeDataToWindow(&fakeNode); @@ -574,8 +562,7 @@ void CHyprDwindleLayout::recalculateMonitor(const int& monid) { const auto TOPNODE = getMasterNodeOnWorkspace(PMONITOR->activeWorkspace); if (TOPNODE && PMONITOR) { - TOPNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; - TOPNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight; + TOPNODE->box = {PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft, PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight}; TOPNODE->recalcSizePosRecursive(); } } @@ -620,7 +607,7 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn m_PseudoDragFlags.started = true; const auto pseudoSize = PWINDOW->m_vRealSize.goalv(); - const auto mouseOffset = g_pInputManager->getMouseCoordsInternal() - (PNODE->position + ((PNODE->size / 2) - (pseudoSize / 2))); + const auto mouseOffset = g_pInputManager->getMouseCoordsInternal() - (PNODE->box.pos() + ((PNODE->box.size() / 2) - (pseudoSize / 2))); if (mouseOffset.x > 0 && mouseOffset.x < pseudoSize.x && mouseOffset.y > 0 && mouseOffset.y < pseudoSize.y) { m_PseudoDragFlags.pseudo = true; @@ -643,8 +630,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn else PWINDOW->m_vPseudoSize.y -= pixResize.y * 2; - PWINDOW->m_vPseudoSize.x = std::clamp(PWINDOW->m_vPseudoSize.x, 30.0, PNODE->size.x); - PWINDOW->m_vPseudoSize.y = std::clamp(PWINDOW->m_vPseudoSize.y, 30.0, PNODE->size.y); + PWINDOW->m_vPseudoSize.x = std::clamp(PWINDOW->m_vPseudoSize.x, 30.0, PNODE->box.w); + PWINDOW->m_vPseudoSize.y = std::clamp(PWINDOW->m_vPseudoSize.y, 30.0, PNODE->box.h); PWINDOW->m_vLastFloatingSize = PWINDOW->m_vPseudoSize; PNODE->recalcSizePosRecursive(*PANIMATE == 0); @@ -691,30 +678,30 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn } if (PHOUTER) { - PHOUTER->pParent->splitRatio = std::clamp(PHOUTER->pParent->splitRatio + allowedMovement.x * 2.f / PHOUTER->pParent->size.x, 0.1, 1.9); + PHOUTER->pParent->splitRatio = std::clamp(PHOUTER->pParent->splitRatio + allowedMovement.x * 2.f / PHOUTER->pParent->box.w, 0.1, 1.9); if (PHINNER) { - const auto ORIGINAL = PHINNER->size.x; + const auto ORIGINAL = PHINNER->box.w; PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0); if (PHINNER->pParent->children[0] == PHINNER) - PHINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.x) / PHINNER->pParent->size.x * 2.f, 0.1, 1.9); + PHINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.x) / PHINNER->pParent->box.w * 2.f, 0.1, 1.9); else - PHINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.x) / PHINNER->pParent->size.x * 2.f, 0.1, 1.9); + PHINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.x) / PHINNER->pParent->box.w * 2.f, 0.1, 1.9); PHINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0); } else PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0); } if (PVOUTER) { - PVOUTER->pParent->splitRatio = std::clamp(PVOUTER->pParent->splitRatio + allowedMovement.y * 2.f / PVOUTER->pParent->size.y, 0.1, 1.9); + PVOUTER->pParent->splitRatio = std::clamp(PVOUTER->pParent->splitRatio + allowedMovement.y * 2.f / PVOUTER->pParent->box.h, 0.1, 1.9); if (PVINNER) { - const auto ORIGINAL = PVINNER->size.y; + const auto ORIGINAL = PVINNER->box.h; PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0); if (PVINNER->pParent->children[0] == PVINNER) - PVINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.y) / PVINNER->pParent->size.y * 2.f, 0.1, 1.9); + PVINNER->pParent->splitRatio = std::clamp((ORIGINAL - allowedMovement.y) / PVINNER->pParent->box.h * 2.f, 0.1, 1.9); else - PVINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.y) / PVINNER->pParent->size.y * 2.f, 0.1, 1.9); + PVINNER->pParent->splitRatio = std::clamp(2 - (ORIGINAL + allowedMovement.y) / PVINNER->pParent->box.h * 2.f, 0.1, 1.9); PVINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0); } else PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0); @@ -734,11 +721,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn // No parent means we have only 2 windows, and thus one axis of freedom if (!PPARENT2) { if (PARENTSIDEBYSIDE) { - allowedMovement.x *= 2.f / PPARENT->size.x; + allowedMovement.x *= 2.f / PPARENT->box.w; PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9); PPARENT->recalcSizePosRecursive(*PANIMATE == 0); } else { - allowedMovement.y *= 2.f / PPARENT->size.y; + allowedMovement.y *= 2.f / PPARENT->box.h; PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9); PPARENT->recalcSizePosRecursive(*PANIMATE == 0); } @@ -753,11 +740,11 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn // no parent, one axis of freedom if (!PPARENT2) { if (PARENTSIDEBYSIDE) { - allowedMovement.x *= 2.f / PPARENT->size.x; + allowedMovement.x *= 2.f / PPARENT->box.w; PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.x, 0.1, 1.9); PPARENT->recalcSizePosRecursive(*PANIMATE == 0); } else { - allowedMovement.y *= 2.f / PPARENT->size.y; + allowedMovement.y *= 2.f / PPARENT->box.h; PPARENT->splitRatio = std::clamp(PPARENT->splitRatio + allowedMovement.y, 0.1, 1.9); PPARENT->recalcSizePosRecursive(*PANIMATE == 0); } @@ -769,8 +756,8 @@ void CHyprDwindleLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorn const auto SIDECONTAINER = PARENTSIDEBYSIDE ? PPARENT : PPARENT2; const auto TOPCONTAINER = PARENTSIDEBYSIDE ? PPARENT2 : PPARENT; - allowedMovement.x *= 2.f / SIDECONTAINER->size.x; - allowedMovement.y *= 2.f / TOPCONTAINER->size.y; + allowedMovement.x *= 2.f / SIDECONTAINER->box.w; + allowedMovement.y *= 2.f / TOPCONTAINER->box.h; SIDECONTAINER->splitRatio = std::clamp(SIDECONTAINER->splitRatio + allowedMovement.x, 0.1, 1.9); TOPCONTAINER->splitRatio = std::clamp(TOPCONTAINER->splitRatio + allowedMovement.y, 0.1, 1.9); @@ -838,11 +825,10 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree SDwindleNodeData fakeNode; fakeNode.pWindow = pWindow; - fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; - fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight; + fakeNode.box = {PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft, PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight}; fakeNode.workspaceID = pWindow->m_iWorkspaceID; - pWindow->m_vPosition = fakeNode.position; - pWindow->m_vSize = fakeNode.size; + pWindow->m_vPosition = fakeNode.box.pos(); + pWindow->m_vSize = fakeNode.box.size(); applyNodeDataToWindow(&fakeNode); } @@ -954,17 +940,15 @@ void CHyprDwindleLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) { } if (ACTIVE1) { - ACTIVE1->position = PNODE->position; - ACTIVE1->size = PNODE->size; - ACTIVE1->pWindow->m_vPosition = ACTIVE1->position; - ACTIVE1->pWindow->m_vSize = ACTIVE1->size; + ACTIVE1->box = PNODE->box; + ACTIVE1->pWindow->m_vPosition = ACTIVE1->box.pos(); + ACTIVE1->pWindow->m_vSize = ACTIVE1->box.size(); } if (ACTIVE2) { - ACTIVE2->position = PNODE2->position; - ACTIVE2->size = PNODE2->size; - ACTIVE2->pWindow->m_vPosition = ACTIVE2->position; - ACTIVE2->pWindow->m_vSize = ACTIVE2->size; + ACTIVE2->box = PNODE2->box; + ACTIVE2->pWindow->m_vPosition = ACTIVE2->box.pos(); + ACTIVE2->pWindow->m_vSize = ACTIVE2->box.size(); } g_pHyprRenderer->damageWindow(pWindow); diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp index 7db9066f..c2d47d88 100644 --- a/src/layout/DwindleLayout.hpp +++ b/src/layout/DwindleLayout.hpp @@ -21,8 +21,7 @@ struct SDwindleNodeData { bool splitTop = false; // for preserve_split - Vector2D position; - Vector2D size; + CBox box = {0}; int workspaceID = -1; @@ -34,8 +33,8 @@ struct SDwindleNodeData { // For list lookup bool operator==(const SDwindleNodeData& rhs) const { - return pWindow == rhs.pWindow && workspaceID == rhs.workspaceID && position == rhs.position && size == rhs.size && pParent == rhs.pParent && - children[0] == rhs.children[0] && children[1] == rhs.children[1]; + return pWindow == rhs.pWindow && workspaceID == rhs.workspaceID && box == rhs.box && pParent == rhs.pParent && children[0] == rhs.children[0] && + children[1] == rhs.children[1]; } void recalcSizePosRecursive(bool force = false, bool horizontalOverride = false, bool verticalOverride = false); @@ -96,7 +95,7 @@ struct std::formatter : std::formatter { auto out = ctx.out(); if (!node) return std::format_to(out, "[Node nullptr]"); - std::format_to(out, "[Node {:x}: workspace: {}, pos: {:j2}, size: {:j2}", (uintptr_t)node, node->workspaceID, node->position, node->size); + std::format_to(out, "[Node {:x}: workspace: {}, pos: {:j2}, size: {:j2}", (uintptr_t)node, node->workspaceID, node->box.pos(), node->box.size()); if (!node->isNode && node->pWindow) std::format_to(out, ", window: {:x}", node->pWindow); return std::format_to(out, "]"); From 56dec1c6a28c59b11c00e1b727517484ec4fb5ac Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 4 Nov 2023 22:25:09 +0000 Subject: [PATCH 177/513] renderer: properly set currentFB on snapshot renders --- src/render/OpenGL.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index b8028c3f..690b0ede 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1495,6 +1495,8 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(CWindow* pWindow, CFramebuffer* pFra pFramebuffer->bind(); + m_RenderData.currentFB = pFramebuffer; + clear(CColor(0, 0, 0, 0)); // JIC g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, false, RENDER_PASS_ALL, true); @@ -1553,6 +1555,8 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) { PFRAMEBUFFER->bind(); + m_RenderData.currentFB = PFRAMEBUFFER; + clear(CColor(0, 0, 0, 0)); // JIC g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders, RENDER_PASS_ALL); @@ -1598,6 +1602,8 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) { PFRAMEBUFFER->bind(); + m_RenderData.currentFB = PFRAMEBUFFER; + clear(CColor(0, 0, 0, 0)); // JIC timespec now; From d3e5796ee1d298b3819d04febaae58ceb9230e5b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 4 Nov 2023 23:00:20 +0000 Subject: [PATCH 178/513] layout: fix missed setWindowSize in no_gaps_when_only node apply fixes #3758 --- src/layout/DwindleLayout.cpp | 2 ++ src/layout/MasterLayout.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 2eb428ab..eed06751 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -158,6 +158,8 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for PWINDOW->updateWindowDecos(); + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv()); + return; } diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index e3b7b7ab..46a05aa8 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -668,6 +668,8 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { PWINDOW->updateWindowDecos(); + g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv()); + return; } From 92e535025ee386b2c1421f2f414d00f34737d0a7 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 4 Nov 2023 23:12:08 +0000 Subject: [PATCH 179/513] region: include box in the header --- src/helpers/Region.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/helpers/Region.hpp b/src/helpers/Region.hpp index 94b639c9..80153cff 100644 --- a/src/helpers/Region.hpp +++ b/src/helpers/Region.hpp @@ -2,6 +2,7 @@ #include #include #include "Vector2D.hpp" +#include "Box.hpp" struct wlr_box; From 3b786419d817a76b834d5e010afbed4d0cf98804 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 5 Nov 2023 00:32:22 +0000 Subject: [PATCH 180/513] subprojects: update tracy --- subprojects/tracy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/tracy b/subprojects/tracy index 897aec5b..37aff70d 160000 --- a/subprojects/tracy +++ b/subprojects/tracy @@ -1 +1 @@ -Subproject commit 897aec5b062664d2485f4f9a213715d2e527e0ca +Subproject commit 37aff70dfa50cf6307b3fee6074d627dc2929143 From 94049727327de8bf087184b0e2b386a5bc2563ba Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 5 Nov 2023 14:12:55 +0000 Subject: [PATCH 181/513] events: set reported size on floating map fixes #3767 --- src/events/Windows.cpp | 3 +-- src/layout/IHyprLayout.cpp | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 23559773..f131efa4 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -653,8 +653,7 @@ void Events::listener_mapWindow(void* owner, void* data) { g_pInputManager->simulateMouseMovement(); // fix some xwayland apps that don't behave nicely - PWINDOW->m_vPendingReportedSize = PWINDOW->m_vRealSize.goalv(); - PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; + PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; } void Events::listener_unmapWindow(void* owner, void* data) { diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index f9f8ab59..22816716 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -162,7 +162,8 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) { g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv()); g_pCompositor->changeWindowZOrder(pWindow, true); - } + } else + pWindow->m_vPendingReportedSize = pWindow->m_vRealSize.goalv(); } void IHyprLayout::onBeginDragWindow() { From c4e1a9b13baf9a0f8b58824803c4a9e63cbc41b3 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 5 Nov 2023 14:47:24 +0000 Subject: [PATCH 182/513] box: use std::round instead of std::floor in ::round() fixes #3761, possibly also #3511 --- src/helpers/Box.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/helpers/Box.cpp b/src/helpers/Box.cpp index e71ed622..55300f5f 100644 --- a/src/helpers/Box.cpp +++ b/src/helpers/Box.cpp @@ -58,12 +58,12 @@ CBox& CBox::applyFromWlr() { } CBox& CBox::round() { - float newW = x + w - std::floor(x); - float newH = y + h - std::floor(y); - x = std::floor(x); - y = std::floor(y); - w = std::floor(newW); - h = std::floor(newH); + float newW = x + w - std::round(x); + float newH = y + h - std::round(y); + x = std::round(x); + y = std::round(y); + w = std::round(newW); + h = std::round(newH); return *this; } From d8b7ded18c47e5e10d21ac162a42256d573a9e91 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 5 Nov 2023 16:18:41 +0000 Subject: [PATCH 183/513] compositor: find windows in direction on floating --- src/Compositor.cpp | 157 +++++++++++++++++++++++----------- src/helpers/MiscFunctions.cpp | 4 + src/helpers/MiscFunctions.hpp | 1 + src/helpers/Vector2D.cpp | 4 + src/helpers/Vector2D.hpp | 2 +- 5 files changed, 115 insertions(+), 53 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 74ac7c11..4f655c16 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1501,6 +1501,9 @@ void CCompositor::addToFadingOutSafe(CWindow* pWindow) { CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) { + if (!isDirection(dir)) + return nullptr; + // 0 -> history, 1 -> shared length static auto* const PMETHOD = &g_pConfigManager->getConfigValuePtr("binds:focus_preferred_method")->intValue; @@ -1515,77 +1518,127 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) { const auto POSA = Vector2D(WINDOWIDEALBB.x, WINDOWIDEALBB.y); const auto SIZEA = Vector2D(WINDOWIDEALBB.width, WINDOWIDEALBB.height); + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); auto leaderValue = -1; CWindow* leaderWindow = nullptr; - for (auto& w : m_vWindows) { - if (w.get() == pWindow || !w->m_bIsMapped || w->isHidden() || w->m_bIsFloating || !isWorkspaceVisible(w->m_iWorkspaceID)) - continue; + if (!pWindow->m_bIsFloating) { - if (pWindow->m_iMonitorID == w->m_iMonitorID && pWindow->m_iWorkspaceID != w->m_iWorkspaceID) - continue; + // for tiled windows, we calc edges + for (auto& w : m_vWindows) { + if (w.get() == pWindow || !w->m_bIsMapped || w->isHidden() || w->m_bIsFloating || !isWorkspaceVisible(w->m_iWorkspaceID)) + continue; - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID); - if (PWORKSPACE->m_bHasFullscreenWindow && !w->m_bIsFullscreen && !w->m_bCreatedOverFullscreen) - continue; + if (pWindow->m_iMonitorID == w->m_iMonitorID && pWindow->m_iWorkspaceID != w->m_iWorkspaceID) + continue; - const auto BWINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved(); + if (PWORKSPACE->m_bHasFullscreenWindow && !w->m_bIsFullscreen && !w->m_bCreatedOverFullscreen) + continue; - const auto POSB = Vector2D(BWINDOWIDEALBB.x, BWINDOWIDEALBB.y); - const auto SIZEB = Vector2D(BWINDOWIDEALBB.width, BWINDOWIDEALBB.height); + const auto BWINDOWIDEALBB = w->getWindowIdealBoundingBoxIgnoreReserved(); - double intersectLength = -1; + const auto POSB = Vector2D(BWINDOWIDEALBB.x, BWINDOWIDEALBB.y); + const auto SIZEB = Vector2D(BWINDOWIDEALBB.width, BWINDOWIDEALBB.height); - switch (dir) { - case 'l': - if (STICKS(POSA.x, POSB.x + SIZEB.x)) { - intersectLength = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y)); - } - break; - case 'r': - if (STICKS(POSA.x + SIZEA.x, POSB.x)) { - intersectLength = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y)); - } - break; - case 't': - case 'u': - if (STICKS(POSA.y, POSB.y + SIZEB.y)) { - intersectLength = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x)); - } - break; - case 'b': - case 'd': - if (STICKS(POSA.y + SIZEA.y, POSB.y)) { - intersectLength = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x)); - } - break; - } + double intersectLength = -1; - if (*PMETHOD == 0 /* history */) { - if (intersectLength > 0) { + switch (dir) { + case 'l': + if (STICKS(POSA.x, POSB.x + SIZEB.x)) { + intersectLength = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y)); + } + break; + case 'r': + if (STICKS(POSA.x + SIZEA.x, POSB.x)) { + intersectLength = std::max(0.0, std::min(POSA.y + SIZEA.y, POSB.y + SIZEB.y) - std::max(POSA.y, POSB.y)); + } + break; + case 't': + case 'u': + if (STICKS(POSA.y, POSB.y + SIZEB.y)) { + intersectLength = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x)); + } + break; + case 'b': + case 'd': + if (STICKS(POSA.y + SIZEA.y, POSB.y)) { + intersectLength = std::max(0.0, std::min(POSA.x + SIZEA.x, POSB.x + SIZEB.x) - std::max(POSA.x, POSB.x)); + } + break; + } - // get idx - int windowIDX = -1; - for (size_t i = 0; i < g_pCompositor->m_vWindowFocusHistory.size(); ++i) { - if (g_pCompositor->m_vWindowFocusHistory[i] == w.get()) { - windowIDX = i; - break; + if (*PMETHOD == 0 /* history */) { + if (intersectLength > 0) { + + // get idx + int windowIDX = -1; + for (size_t i = 0; i < g_pCompositor->m_vWindowFocusHistory.size(); ++i) { + if (g_pCompositor->m_vWindowFocusHistory[i] == w.get()) { + windowIDX = i; + break; + } + } + + windowIDX = g_pCompositor->m_vWindowFocusHistory.size() - windowIDX; + + if (windowIDX > leaderValue) { + leaderValue = windowIDX; + leaderWindow = w.get(); } } - - windowIDX = g_pCompositor->m_vWindowFocusHistory.size() - windowIDX; - - if (windowIDX > leaderValue) { - leaderValue = windowIDX; + } else /* length */ { + if (intersectLength > leaderValue) { + leaderValue = intersectLength; leaderWindow = w.get(); } } - } else /* length */ { - if (intersectLength > leaderValue) { - leaderValue = intersectLength; + } + } else { + // for floating windows, we calculate best distance and angle. + // if there is a window with angle better than THRESHOLD, only distance counts + + if (dir == 'u') + dir = 't'; + if (dir == 'd') + dir = 'b'; + + static const std::unordered_map VECTORS = {{'r', {1, 0}}, {'t', {0, -1}}, {'b', {0, 1}}, {'l', {-1, 0}}}; + + // + auto vectorAngles = [](Vector2D a, Vector2D b) -> double { + double dot = a.x * b.x + a.y * b.y; + double ang = std::acos(dot / (a.size() * b.size())); + return ang; + }; + + float bestAngleAbs = 2.0 * M_PI; + constexpr float THRESHOLD = 0.3 * M_PI; + + for (auto& w : m_vWindows) { + if (w.get() == pWindow || !w->m_bIsMapped || w->isHidden() || !w->m_bIsFloating || !isWorkspaceVisible(w->m_iWorkspaceID)) + continue; + + if (pWindow->m_iMonitorID == w->m_iMonitorID && pWindow->m_iWorkspaceID != w->m_iWorkspaceID) + continue; + + if (PWORKSPACE->m_bHasFullscreenWindow && !w->m_bIsFullscreen && !w->m_bCreatedOverFullscreen) + continue; + + const auto DIST = w->middle().distance(pWindow->middle()); + const auto ANGLE = vectorAngles(Vector2D{w->middle() - pWindow->middle()}, VECTORS.at(dir)); + + if (ANGLE > M_PI_2) + continue; // if the angle is over 90 degrees, ignore. Wrong direction entirely. + + if ((bestAngleAbs < THRESHOLD && DIST < leaderValue && ANGLE < THRESHOLD) || (ANGLE < bestAngleAbs && bestAngleAbs > THRESHOLD) || leaderValue == -1) { + leaderValue = DIST; + bestAngleAbs = ANGLE; leaderWindow = w.get(); } } + + if (!leaderWindow && PWORKSPACE->m_bHasFullscreenWindow) + leaderWindow = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); } if (leaderValue != -1) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index b3a8ade7..376ac032 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -242,6 +242,10 @@ bool isDirection(const std::string& arg) { return arg == "l" || arg == "r" || arg == "u" || arg == "d" || arg == "t" || arg == "b"; } +bool isDirection(const char& arg) { + return arg == 'l' || arg == 'r' || arg == 'u' || arg == 'd' || arg == 't' || arg == 'b'; +} + int getWorkspaceIDFromString(const std::string& in, std::string& outName) { int result = INT_MAX; if (in.starts_with("special")) { diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 3bb07f79..b2fe5858 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -19,6 +19,7 @@ std::string escapeJSONStrings(const std::string& str); std::string removeBeginEndSpacesTabs(std::string); bool isNumber(const std::string&, bool allowfloat = false); bool isDirection(const std::string&); +bool isDirection(const char&); int getWorkspaceIDFromString(const std::string&, std::string&); std::optional cleanCmdForWorkspace(const std::string&, std::string); float vecToRectDistanceSquared(const Vector2D& vec, const Vector2D& p1, const Vector2D& p2); diff --git a/src/helpers/Vector2D.cpp b/src/helpers/Vector2D.cpp index 118ba9d9..ae2484b3 100644 --- a/src/helpers/Vector2D.cpp +++ b/src/helpers/Vector2D.cpp @@ -45,3 +45,7 @@ bool Vector2D::inTriangle(const Vector2D& p1, const Vector2D& p2, const Vector2D return 0 <= a && a <= 1 && 0 <= b && b <= 1 && 0 <= c && c <= 1; } + +double Vector2D::size() const { + return std::sqrt(x * x + y * y); +} diff --git a/src/helpers/Vector2D.hpp b/src/helpers/Vector2D.hpp index 6112b8e4..17415289 100644 --- a/src/helpers/Vector2D.hpp +++ b/src/helpers/Vector2D.hpp @@ -57,7 +57,7 @@ class Vector2D { } double distance(const Vector2D& other) const; - + double size() const; Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D()) const; Vector2D floor() const; From 55825c301e5f437566e042d7036bc29a2e48257b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 5 Nov 2023 16:21:47 +0000 Subject: [PATCH 184/513] compositor: allow windowfromregex floating param fixes #3766 --- src/Compositor.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 4f655c16..fc45496e 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2350,6 +2350,19 @@ CWindow* CCompositor::getWindowByRegex(const std::string& regexp) { } else if (regexp.starts_with("pid:")) { mode = MODE_PID; matchCheck = regexp.substr(4); + } else if (regexp.starts_with("floating")) { + // first floating on the current ws + if (!m_pLastWindow) + return nullptr; + + for (auto& w : m_vWindows) { + if (!w->m_bIsMapped || !w->m_bIsFloating || w->m_iWorkspaceID != m_pLastWindow->m_iWorkspaceID || w->isHidden()) + continue; + + return w.get(); + } + + return nullptr; } for (auto& w : g_pCompositor->m_vWindows) { From 600a128f83c9f6d6cf37d4e9de6bf9001d321bd0 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 5 Nov 2023 16:22:43 +0000 Subject: [PATCH 185/513] compositor: allow windowfromregex tiled param --- src/Compositor.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index fc45496e..30e9fdb6 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2350,13 +2350,15 @@ CWindow* CCompositor::getWindowByRegex(const std::string& regexp) { } else if (regexp.starts_with("pid:")) { mode = MODE_PID; matchCheck = regexp.substr(4); - } else if (regexp.starts_with("floating")) { + } else if (regexp.starts_with("floating") || regexp.starts_with("tiled")) { // first floating on the current ws if (!m_pLastWindow) return nullptr; + const bool FLOAT = regexp.starts_with("floating"); + for (auto& w : m_vWindows) { - if (!w->m_bIsMapped || !w->m_bIsFloating || w->m_iWorkspaceID != m_pLastWindow->m_iWorkspaceID || w->isHidden()) + if (!w->m_bIsMapped || w->m_bIsFloating != FLOAT || w->m_iWorkspaceID != m_pLastWindow->m_iWorkspaceID || w->isHidden()) continue; return w.get(); From a122271f096076ab34750dbbf6914422e7481410 Mon Sep 17 00:00:00 2001 From: Brett Alcox Date: Sun, 5 Nov 2023 11:32:27 -0600 Subject: [PATCH 186/513] includes: fix box headers (#3771) --- src/helpers/Box.hpp | 4 ++-- src/includes.hpp | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/helpers/Box.hpp b/src/helpers/Box.hpp index a5f24d7b..592bb417 100644 --- a/src/helpers/Box.hpp +++ b/src/helpers/Box.hpp @@ -1,8 +1,8 @@ #pragma once -#include #include "Vector2D.hpp" #include "../SharedDefs.hpp" +#include "../includes.hpp" class CBox { public: @@ -77,4 +77,4 @@ class CBox { CBox roundInternal(); wlr_box m_bWlrBox; -}; \ No newline at end of file +}; diff --git a/src/includes.hpp b/src/includes.hpp index b6f357bf..a89f0950 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -105,6 +105,7 @@ extern "C" { #include #include #include +#include #include From 0476e1b498265f12d719da522a615c19241a076d Mon Sep 17 00:00:00 2001 From: David Leal <65901588+dlealmt@users.noreply.github.com> Date: Sun, 5 Nov 2023 19:25:50 +0000 Subject: [PATCH 187/513] groups: add option to configure font name (#3751) --- src/config/ConfigManager.cpp | 1 + src/render/decorations/CHyprGroupBarDecoration.cpp | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f5b9416b..760e9e87 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -129,6 +129,7 @@ void CConfigManager::setDefaultVars() { configValues["group:insert_after_current"].intValue = 1; configValues["group:focus_removed_window"].intValue = 1; + configValues["group:groupbar:font_family"].strValue = "Sans"; configValues["group:groupbar:font_size"].intValue = 8; configValues["group:groupbar:gradients"].intValue = 1; configValues["group:groupbar:render_titles"].intValue = 1; diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index df269bce..873186c0 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -179,8 +179,9 @@ CTitleTex::CTitleTex(CWindow* pWindow, const Vector2D& bufferSize) { const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, bufferSize.x, bufferSize.y); const auto CAIRO = cairo_create(CAIROSURFACE); - static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue; - static auto* const PTEXTCOLOR = &g_pConfigManager->getConfigValuePtr("group:groupbar:text_color")->intValue; + static auto* const PTITLEFONTFAMILY = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_family")->strValue; + static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue; + static auto* const PTEXTCOLOR = &g_pConfigManager->getConfigValuePtr("group:groupbar:text_color")->intValue; const CColor COLOR = CColor(*PTEXTCOLOR); @@ -194,7 +195,7 @@ CTitleTex::CTitleTex(CWindow* pWindow, const Vector2D& bufferSize) { PangoLayout* layout = pango_cairo_create_layout(CAIRO); pango_layout_set_text(layout, szContent.c_str(), -1); - PangoFontDescription* fontDesc = pango_font_description_from_string("Sans"); + PangoFontDescription* fontDesc = pango_font_description_from_string(PTITLEFONTFAMILY->c_str()); pango_font_description_set_size(fontDesc, *PTITLEFONTSIZE * PANGO_SCALE); pango_layout_set_font_description(layout, fontDesc); pango_font_description_free(fontDesc); From ecf98069f655a4e54943ec70d638ddcf429211d1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 5 Nov 2023 19:57:11 +0000 Subject: [PATCH 188/513] layout: round window boxes after special scale factor fixes #3761 again --- src/layout/DwindleLayout.cpp | 9 ++++++--- src/layout/MasterLayout.cpp | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index eed06751..6602c758 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -207,10 +207,13 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for // if special, we adjust the coords a bit static auto* const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("dwindle:special_scale_factor")->floatValue; - PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f; - PWINDOW->m_vRealSize = calcSize * *PSCALEFACTOR; + CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR}; + wb.round(); // avoid rounding mess - g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * *PSCALEFACTOR); + PWINDOW->m_vRealPosition = wb.pos(); + PWINDOW->m_vRealSize = wb.size(); + + g_pXWaylandManager->setWindowSize(PWINDOW, wb.size()); } else { PWINDOW->m_vRealSize = calcSize; PWINDOW->m_vRealPosition = calcPos; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 46a05aa8..e29addfd 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -692,10 +692,13 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID)) { static auto* const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("master:special_scale_factor")->floatValue; - PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f; - PWINDOW->m_vRealSize = calcSize * *PSCALEFACTOR; + CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR}; + wb.round(); // avoid rounding mess - g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * *PSCALEFACTOR); + PWINDOW->m_vRealPosition = wb.pos(); + PWINDOW->m_vRealSize = wb.size(); + + g_pXWaylandManager->setWindowSize(PWINDOW, wb.size()); } else { PWINDOW->m_vRealSize = calcSize; PWINDOW->m_vRealPosition = calcPos; From a1b7a5a53d66d6289f1a3036d1aa4daa965c363c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 6 Nov 2023 17:00:37 +0000 Subject: [PATCH 189/513] layout: fix various rounding errors maybe finally will end #3761 --- src/layout/IHyprLayout.cpp | 11 +++++++---- src/layout/MasterLayout.cpp | 9 ++++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 22816716..274acb13 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -361,12 +361,15 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { else if (m_eGrabbedCorner == CORNER_BOTTOMLEFT) newPos = newPos + Vector2D((m_vBeginDragSizeXY - newSize).x, 0); + CBox wb = {newPos, newSize}; + wb.round(); + if (*PANIMATE) { - DRAGGINGWINDOW->m_vRealSize = newSize; - DRAGGINGWINDOW->m_vRealPosition = newPos; + DRAGGINGWINDOW->m_vRealSize = wb.size(); + DRAGGINGWINDOW->m_vRealPosition = wb.pos(); } else { - DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(newSize); - DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(newPos); + DRAGGINGWINDOW->m_vRealSize.setValueAndWarp(wb.size()); + DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos()); } g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv()); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index e29addfd..57784786 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -700,10 +700,13 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { g_pXWaylandManager->setWindowSize(PWINDOW, wb.size()); } else { - PWINDOW->m_vRealSize = calcSize; - PWINDOW->m_vRealPosition = calcPos; + CBox wb = {calcPos, calcSize}; + wb.round(); // avoid rounding mess - g_pXWaylandManager->setWindowSize(PWINDOW, calcSize); + PWINDOW->m_vRealPosition = wb.pos(); + PWINDOW->m_vRealSize = wb.size(); + + g_pXWaylandManager->setWindowSize(PWINDOW, wb.size()); } if (m_bForceWarps && !*PANIMATE) { From 29e0a7112ef5c412e4af640b9d80f80b81a26c94 Mon Sep 17 00:00:00 2001 From: Visual-Dawg Date: Mon, 6 Nov 2023 20:49:03 +0200 Subject: [PATCH 190/513] renderer: added new customization options to the blur shaders (#3650) Adds to `decoration:blur:` `vibrancy` and `vibrancy_darkness` --- example/hyprland.conf | 2 + src/config/ConfigManager.cpp | 58 +++++----- src/render/OpenGL.cpp | 77 ++++++++----- src/render/OpenGL.hpp | 1 + src/render/Shader.hpp | 18 ++- src/render/shaders/Textures.hpp | 190 +++++++++++++++++++++++++++++--- 6 files changed, 266 insertions(+), 80 deletions(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index 698335ea..0f830ec3 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -63,6 +63,8 @@ decoration { enabled = true size = 3 passes = 1 + + vibrancy = 0.1696 } drop_shadow = true diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 760e9e87..d07e6a6a 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -153,34 +153,36 @@ void CConfigManager::setDefaultVars() { configValues["debug:suppress_errors"].intValue = 0; configValues["debug:watchdog_timeout"].intValue = 5; - configValues["decoration:rounding"].intValue = 0; - configValues["decoration:blur:enabled"].intValue = 1; - configValues["decoration:blur:size"].intValue = 8; - configValues["decoration:blur:passes"].intValue = 1; - configValues["decoration:blur:ignore_opacity"].intValue = 0; - configValues["decoration:blur:new_optimizations"].intValue = 1; - configValues["decoration:blur:xray"].intValue = 0; - configValues["decoration:blur:noise"].floatValue = 0.0117; - configValues["decoration:blur:contrast"].floatValue = 0.8916; - configValues["decoration:blur:brightness"].floatValue = 0.8172; - configValues["decoration:blur:special"].intValue = 0; - configValues["decoration:active_opacity"].floatValue = 1; - configValues["decoration:inactive_opacity"].floatValue = 1; - configValues["decoration:fullscreen_opacity"].floatValue = 1; - configValues["decoration:no_blur_on_oversized"].intValue = 0; - configValues["decoration:drop_shadow"].intValue = 1; - configValues["decoration:shadow_range"].intValue = 4; - configValues["decoration:shadow_render_power"].intValue = 3; - configValues["decoration:shadow_ignore_window"].intValue = 1; - configValues["decoration:shadow_offset"].vecValue = Vector2D(); - configValues["decoration:shadow_scale"].floatValue = 1.f; - configValues["decoration:col.shadow"].intValue = 0xee1a1a1a; - configValues["decoration:col.shadow_inactive"].intValue = INT_MAX; - configValues["decoration:dim_inactive"].intValue = 0; - configValues["decoration:dim_strength"].floatValue = 0.5f; - configValues["decoration:dim_special"].floatValue = 0.2f; - configValues["decoration:dim_around"].floatValue = 0.4f; - configValues["decoration:screen_shader"].strValue = STRVAL_EMPTY; + configValues["decoration:rounding"].intValue = 0; + configValues["decoration:blur:enabled"].intValue = 1; + configValues["decoration:blur:size"].intValue = 8; + configValues["decoration:blur:passes"].intValue = 1; + configValues["decoration:blur:ignore_opacity"].intValue = 0; + configValues["decoration:blur:new_optimizations"].intValue = 1; + configValues["decoration:blur:xray"].intValue = 0; + configValues["decoration:blur:contrast"].floatValue = 0.8916; + configValues["decoration:blur:brightness"].floatValue = 1.0; + configValues["decoration:blur:vibrancy"].floatValue = 0.1696; + configValues["decoration:blur:vibrancy_darkness"].floatValue = 0.0; + configValues["decoration:blur:noise"].floatValue = 0.0117; + configValues["decoration:blur:special"].intValue = 0; + configValues["decoration:active_opacity"].floatValue = 1; + configValues["decoration:inactive_opacity"].floatValue = 1; + configValues["decoration:fullscreen_opacity"].floatValue = 1; + configValues["decoration:no_blur_on_oversized"].intValue = 0; + configValues["decoration:drop_shadow"].intValue = 1; + configValues["decoration:shadow_range"].intValue = 4; + configValues["decoration:shadow_render_power"].intValue = 3; + configValues["decoration:shadow_ignore_window"].intValue = 1; + configValues["decoration:shadow_offset"].vecValue = Vector2D(); + configValues["decoration:shadow_scale"].floatValue = 1.f; + configValues["decoration:col.shadow"].intValue = 0xee1a1a1a; + configValues["decoration:col.shadow_inactive"].intValue = INT_MAX; + configValues["decoration:dim_inactive"].intValue = 0; + configValues["decoration:dim_strength"].floatValue = 0.5f; + configValues["decoration:dim_special"].floatValue = 0.2f; + configValues["decoration:dim_around"].floatValue = 0.4f; + configValues["decoration:screen_shader"].strValue = STRVAL_EMPTY; configValues["dwindle:pseudotile"].intValue = 0; configValues["dwindle:force_split"].intValue = 0; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 690b0ede..e047f287 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -307,15 +307,18 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shEXT.applyTint = glGetUniformLocation(prog, "applyTint"); m_RenderData.pCurrentMonData->m_shEXT.tint = glGetUniformLocation(prog, "tint"); - prog = createProgram(TEXVERTSRC, FRAGBLUR1); - m_RenderData.pCurrentMonData->m_shBLUR1.program = prog; - m_RenderData.pCurrentMonData->m_shBLUR1.tex = glGetUniformLocation(prog, "tex"); - m_RenderData.pCurrentMonData->m_shBLUR1.alpha = glGetUniformLocation(prog, "alpha"); - m_RenderData.pCurrentMonData->m_shBLUR1.proj = glGetUniformLocation(prog, "proj"); - m_RenderData.pCurrentMonData->m_shBLUR1.posAttrib = glGetAttribLocation(prog, "pos"); - m_RenderData.pCurrentMonData->m_shBLUR1.texAttrib = glGetAttribLocation(prog, "texcoord"); - m_RenderData.pCurrentMonData->m_shBLUR1.radius = glGetUniformLocation(prog, "radius"); - m_RenderData.pCurrentMonData->m_shBLUR1.halfpixel = glGetUniformLocation(prog, "halfpixel"); + prog = createProgram(TEXVERTSRC, FRAGBLUR1); + m_RenderData.pCurrentMonData->m_shBLUR1.program = prog; + m_RenderData.pCurrentMonData->m_shBLUR1.tex = glGetUniformLocation(prog, "tex"); + m_RenderData.pCurrentMonData->m_shBLUR1.alpha = glGetUniformLocation(prog, "alpha"); + m_RenderData.pCurrentMonData->m_shBLUR1.proj = glGetUniformLocation(prog, "proj"); + m_RenderData.pCurrentMonData->m_shBLUR1.posAttrib = glGetAttribLocation(prog, "pos"); + m_RenderData.pCurrentMonData->m_shBLUR1.texAttrib = glGetAttribLocation(prog, "texcoord"); + m_RenderData.pCurrentMonData->m_shBLUR1.radius = glGetUniformLocation(prog, "radius"); + m_RenderData.pCurrentMonData->m_shBLUR1.halfpixel = glGetUniformLocation(prog, "halfpixel"); + m_RenderData.pCurrentMonData->m_shBLUR1.passes = glGetUniformLocation(prog, "passes"); + m_RenderData.pCurrentMonData->m_shBLUR1.vibrancy = glGetUniformLocation(prog, "vibrancy"); + m_RenderData.pCurrentMonData->m_shBLUR1.vibrancy_darkness = glGetUniformLocation(prog, "vibrancy_darkness"); prog = createProgram(TEXVERTSRC, FRAGBLUR2); m_RenderData.pCurrentMonData->m_shBLUR2.program = prog; @@ -327,15 +330,23 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shBLUR2.radius = glGetUniformLocation(prog, "radius"); m_RenderData.pCurrentMonData->m_shBLUR2.halfpixel = glGetUniformLocation(prog, "halfpixel"); + prog = createProgram(TEXVERTSRC, FRAGBLURPREPARE); + m_RenderData.pCurrentMonData->m_shBLURPREPARE.program = prog; + m_RenderData.pCurrentMonData->m_shBLURPREPARE.tex = glGetUniformLocation(prog, "tex"); + m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj = glGetUniformLocation(prog, "proj"); + m_RenderData.pCurrentMonData->m_shBLURPREPARE.posAttrib = glGetAttribLocation(prog, "pos"); + m_RenderData.pCurrentMonData->m_shBLURPREPARE.texAttrib = glGetAttribLocation(prog, "texcoord"); + m_RenderData.pCurrentMonData->m_shBLURPREPARE.contrast = glGetUniformLocation(prog, "contrast"); + m_RenderData.pCurrentMonData->m_shBLURPREPARE.brightness = glGetUniformLocation(prog, "brightness"); + prog = createProgram(TEXVERTSRC, FRAGBLURFINISH); m_RenderData.pCurrentMonData->m_shBLURFINISH.program = prog; m_RenderData.pCurrentMonData->m_shBLURFINISH.tex = glGetUniformLocation(prog, "tex"); m_RenderData.pCurrentMonData->m_shBLURFINISH.proj = glGetUniformLocation(prog, "proj"); m_RenderData.pCurrentMonData->m_shBLURFINISH.posAttrib = glGetAttribLocation(prog, "pos"); m_RenderData.pCurrentMonData->m_shBLURFINISH.texAttrib = glGetAttribLocation(prog, "texcoord"); - m_RenderData.pCurrentMonData->m_shBLURFINISH.noise = glGetUniformLocation(prog, "noise"); - m_RenderData.pCurrentMonData->m_shBLURFINISH.contrast = glGetUniformLocation(prog, "contrast"); m_RenderData.pCurrentMonData->m_shBLURFINISH.brightness = glGetUniformLocation(prog, "brightness"); + m_RenderData.pCurrentMonData->m_shBLURFINISH.noise = glGetUniformLocation(prog, "noise"); prog = createProgram(QUADVERTSRC, FRAGSHADOW); m_RenderData.pCurrentMonData->m_shSHADOW.program = prog; @@ -912,8 +923,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); // get the config settings - static auto* const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur:size")->intValue; - static auto* const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur:passes")->intValue; + static auto* const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur:size")->intValue; + static auto* const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur:passes")->intValue; + static auto* const PBLURVIBRANCY = &g_pConfigManager->getConfigValuePtr("decoration:blur:vibrancy")->floatValue; + static auto* const PBLURVIBRANCYDARKNESS = &g_pConfigManager->getConfigValuePtr("decoration:blur:vibrancy_darkness")->floatValue; // prep damage CRegion damage{*originalDamage}; @@ -927,7 +940,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o CFramebuffer* currentRenderToFB = PMIRRORFB; - // begin with color adjustments + // Begin with base color adjustments - global brightness and contrast // TODO: make this a part of the first pass maybe to save on a drawcall? { static auto* const PBLURCONTRAST = &g_pConfigManager->getConfigValuePtr("decoration:blur:contrast")->floatValue; @@ -941,24 +954,23 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glTexParameteri(m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glUseProgram(m_RenderData.pCurrentMonData->m_shBLURFINISH.program); + glUseProgram(m_RenderData.pCurrentMonData->m_shBLURPREPARE.program); #ifndef GLES2 - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_TRUE, glMatrix); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_TRUE, glMatrix); #else wlr_matrix_transpose(glMatrix, glMatrix); glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_FALSE, glMatrix); #endif - glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.contrast, *PBLURCONTRAST); - glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.brightness, *PBLURBRIGHTNESS); + glUniform1f(m_RenderData.pCurrentMonData->m_shBLURPREPARE.contrast, *PBLURCONTRAST); + glUniform1f(m_RenderData.pCurrentMonData->m_shBLURPREPARE.brightness, *PBLURBRIGHTNESS); + glUniform1i(m_RenderData.pCurrentMonData->m_shBLURPREPARE.tex, 0); - glUniform1i(m_RenderData.pCurrentMonData->m_shBLURFINISH.tex, 0); + glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBLURPREPARE.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); + glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBLURPREPARE.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); - glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBLURFINISH.posAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); - glVertexAttribPointer(m_RenderData.pCurrentMonData->m_shBLURFINISH.texAttrib, 2, GL_FLOAT, GL_FALSE, 0, fullVerts); - - glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURFINISH.posAttrib); - glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURFINISH.texAttrib); + glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURPREPARE.posAttrib); + glEnableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURPREPARE.texAttrib); if (!damage.empty()) { for (auto& RECT : damage.getRects()) { @@ -967,8 +979,8 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o } } - glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURFINISH.posAttrib); - glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURFINISH.texAttrib); + glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURPREPARE.posAttrib); + glDisableVertexAttribArray(m_RenderData.pCurrentMonData->m_shBLURPREPARE.texAttrib); currentRenderToFB = PMIRRORSWAPFB; } @@ -996,10 +1008,13 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glUniformMatrix3fv(pShader->proj, 1, GL_FALSE, glMatrix); #endif glUniform1f(pShader->radius, *PBLURSIZE * a); // this makes the blursize change with a - if (pShader == &m_RenderData.pCurrentMonData->m_shBLUR1) + if (pShader == &m_RenderData.pCurrentMonData->m_shBLUR1) { glUniform2f(m_RenderData.pCurrentMonData->m_shBLUR1.halfpixel, 0.5f / (m_RenderData.pMonitor->vecPixelSize.x / 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y / 2.f)); - else + glUniform1i(m_RenderData.pCurrentMonData->m_shBLUR1.passes, *PBLURPASSES); + glUniform1f(m_RenderData.pCurrentMonData->m_shBLUR1.vibrancy, *PBLURVIBRANCY); + glUniform1f(m_RenderData.pCurrentMonData->m_shBLUR1.vibrancy_darkness, *PBLURVIBRANCYDARKNESS); + } else glUniform2f(m_RenderData.pCurrentMonData->m_shBLUR2.halfpixel, 0.5f / (m_RenderData.pMonitor->vecPixelSize.x * 2.f), 0.5f / (m_RenderData.pMonitor->vecPixelSize.y * 2.f)); glUniform1i(pShader->tex, 0); @@ -1045,9 +1060,10 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o drawPass(&m_RenderData.pCurrentMonData->m_shBLUR2, &tempDamage); // up } - // finalize with noise + // finalize the image { - static auto* const PBLURNOISE = &g_pConfigManager->getConfigValuePtr("decoration:blur:noise")->floatValue; + static auto* const PBLURNOISE = &g_pConfigManager->getConfigValuePtr("decoration:blur:noise")->floatValue; + static auto* const PBLURBRIGHTNESS = &g_pConfigManager->getConfigValuePtr("decoration:blur:brightness")->floatValue; if (currentRenderToFB == PMIRRORFB) PMIRRORSWAPFB->bind(); @@ -1069,6 +1085,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_FALSE, glMatrix); #endif glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.noise, *PBLURNOISE); + glUniform1f(m_RenderData.pCurrentMonData->m_shBLURFINISH.brightness, *PBLURBRIGHTNESS); glUniform1i(m_RenderData.pCurrentMonData->m_shBLURFINISH.tex, 0); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 7e3e4e7c..0c6ef13c 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -64,6 +64,7 @@ struct SMonitorRenderData { CShader m_shEXT; CShader m_shBLUR1; CShader m_shBLUR2; + CShader m_shBLURPREPARE; CShader m_shBLURFINISH; CShader m_shSHADOW; CShader m_shBORDER1; diff --git a/src/render/Shader.hpp b/src/render/Shader.hpp index b67f61ef..70fe468c 100644 --- a/src/render/Shader.hpp +++ b/src/render/Shader.hpp @@ -46,13 +46,21 @@ class CShader { GLint distort = -1; GLint output = -1; - GLint noise = -1; - GLint contrast = -1; - GLint brightness = -1; + // Blur prepare + GLint contrast = -1; - GLint getUniformLocation(const std::string&); + // Blur + GLint passes = -1; // Used by `vibrancy` + GLint vibrancy = -1; + GLint vibrancy_darkness = -1; - void destroy(); + // Blur finish + GLint brightness = -1; + GLint noise = -1; + + GLint getUniformLocation(const std::string&); + + void destroy(); private: std::unordered_map m_muUniforms; diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index cf753bb4..15e80410 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -180,12 +180,116 @@ void main() { inline const std::string FRAGBLUR1 = R"#( #version 100 -precision mediump float; +precision mediump float; varying mediump vec2 v_texcoord; // is in 0-1 -uniform sampler2D tex; +uniform sampler2D tex; -uniform float radius; -uniform vec2 halfpixel; +uniform float radius; +uniform vec2 halfpixel; +uniform int passes; +uniform float vibrancy; +uniform float vibrancy_darkness; + +// see http://alienryderflex.com/hsp.html +const float Pr = 0.299; +const float Pg = 0.587; +const float Pb = 0.114; + +// Y is "v" ( brightness ). X is "s" ( saturation ) +// see https://www.desmos.com/3d/a88652b9a4 +// Determines if high brightness or high saturation is more important +const float a = 0.93; +const float b = 0.11; +const float c = 0.66; // Determines the smoothness of the transition of unboosted to boosted colors +// + +// http://www.flong.com/archive/texts/code/shapers_circ/ +float doubleCircleSigmoid(float x, float a) { + float min_param_a = 0.0; + float max_param_a = 1.0; + a = max(min_param_a, min(max_param_a, a)); + + float y = .0; + if (x <= a) { + y = a - sqrt(a * a - x * x); + } else { + y = a + sqrt(pow(1. - a, 2.) - pow(x - 1., 2.)); + } + return y; +} + +vec3 rgb2hsl(vec3 col) { + float red = col.r; + float green = col.g; + float blue = col.b; + + float minc = min(col.r, min(col.g, col.b)); + float maxc = max(col.r, max(col.g, col.b)); + float delta = maxc - minc; + + float lum = (minc + maxc) * 0.5; + float sat = 0.0; + float hue = 0.0; + + if (lum > 0.0 && lum < 1.0) { + float mul = (lum < 0.5) ? (lum) : (1.0 - lum); + sat = delta / (mul * 2.0); + } + + vec3 masks = vec3((maxc == red && maxc != green) ? 1.0 : 0.0, (maxc == green && maxc != blue) ? 1.0 : 0.0, (maxc == blue && maxc != red) ? 1.0 : 0.0); + + vec3 adds = vec3(((green - blue) / delta), 2.0 + ((blue - red) / delta), 4.0 + ((red - green) / delta)); + + float deltaGtz = (delta > 0.0) ? 1.0 : 0.0; + + hue += dot(adds, masks); + hue *= deltaGtz; + hue /= 6.0; + + if (hue < 0.0) + hue += 1.0; + + return vec3(hue, sat, lum); +} +vec3 hsl2rgb(vec3 col) { + const float onethird = 1.0 / 3.0; + const float twothird = 2.0 / 3.0; + const float rcpsixth = 6.0; + + float hue = col.x; + float sat = col.y; + float lum = col.z; + + vec3 xt = vec3(rcpsixth * (hue - twothird), 0.0, rcpsixth * (1.0 - hue)); + + if (hue < twothird) { + xt.r = 0.0; + xt.g = rcpsixth * (twothird - hue); + xt.b = rcpsixth * (hue - onethird); + } + + if (hue < onethird) { + xt.r = rcpsixth * (onethird - hue); + xt.g = rcpsixth * hue; + xt.b = 0.0; + } + + xt = min(xt, 1.0); + + float sat2 = 2.0 * sat; + float satinv = 1.0 - sat; + float luminv = 1.0 - lum; + float lum2m1 = (2.0 * lum) - 1.0; + vec3 ct = (sat2 * xt) + satinv; + + vec3 rgb; + if (lum >= 0.5) + rgb = (luminv * ct) + lum2m1; + else + rgb = lum * ct; + + return rgb; +} void main() { vec2 uv = v_texcoord * 2.0; @@ -196,7 +300,28 @@ void main() { sum += texture2D(tex, uv + vec2(halfpixel.x, -halfpixel.y) * radius); sum += texture2D(tex, uv - vec2(halfpixel.x, -halfpixel.y) * radius); - gl_FragColor = sum / 8.0; + vec4 color = sum / 8.0; + + if (vibrancy == 0.0) { + gl_FragColor = color; + } else { + // Invert it so that it correctly maps to the config setting + float vibrancy_darkness1 = 1.0 - vibrancy_darkness; + + // Decrease the RGB components based on their perceived brightness, to prevent visually dark colors from overblowing the rest. + vec3 hsl = rgb2hsl(color.rgb); + // Calculate perceived brightness, as not boost visually dark colors like deep blue as much as equally saturated yellow + float perceivedBrightness = doubleCircleSigmoid(sqrt(color.r * color.r * Pr + color.g * color.g * Pg + color.b * color.b * Pb), 0.8 * vibrancy_darkness1); + + float b1 = b * vibrancy_darkness1; + float boostBase = hsl[1] > 0.0 ? smoothstep(b1 - c * 0.5, b1 + c * 0.5, 1.0 - (pow(1.0 - hsl[1] * cos(a), 2.0) + pow(1.0 - perceivedBrightness * sin(a), 2.0))) : 0.0; + + float saturation = clamp(hsl[1] + (boostBase * vibrancy) / float(passes), 0.0, 1.0); + + vec3 newColor = hsl2rgb(vec3(hsl[0], saturation, hsl[2])); + + gl_FragColor = vec4(newColor, color[3]); + } } )#"; @@ -226,35 +351,66 @@ void main() { } )#"; -inline const std::string FRAGBLURFINISH = R"#( -precision mediump float; -varying vec2 v_texcoord; // is in 0-1 +inline const std::string FRAGBLURPREPARE = R"#( +precision mediump float; +varying vec2 v_texcoord; // is in 0-1 uniform sampler2D tex; -uniform float contrast; -uniform float noise; -uniform float brightness; +uniform float contrast; +uniform float brightness; -float hash(vec2 p) { - return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453); +float gain(float x, float k) { + float a = 0.5 * pow(2.0 * ((x < 0.5) ? x : 1.0 - x), k); + return (x < 0.5) ? a : 1.0 - a; } void main() { vec4 pixColor = texture2D(tex, v_texcoord); // contrast - pixColor.rgb = (pixColor.rgb - 0.5) * contrast + 0.5; + if (contrast != 1.0) { + pixColor.r = gain(pixColor.r, contrast); + pixColor.g = gain(pixColor.g, contrast); + pixColor.b = gain(pixColor.b, contrast); + } // brightness - pixColor.rgb *= brightness; + if (brightness > 1.0) { + pixColor.rgb *= brightness; + } + + gl_FragColor = pixColor; +} +)#"; + +inline const std::string FRAGBLURFINISH = R"#( +precision mediump float; +varying vec2 v_texcoord; // is in 0-1 +uniform sampler2D tex; + +uniform float noise; +uniform float brightness; + +float hash(vec2 p) { + return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453); +} + +void main() { + vec4 pixColor = texture2D(tex, v_texcoord); // noise - float noiseHash = hash(v_texcoord); + float noiseHash = hash(v_texcoord); float noiseAmount = (mod(noiseHash, 1.0) - 0.5); pixColor.rgb += noiseAmount * noise; + // brightness + if (brightness < 1.0) { + pixColor.rgb *= brightness; + } + gl_FragColor = pixColor; -})#"; +} +)#"; inline const std::string TEXFRAGSRCEXT = R"#( #extension GL_OES_EGL_image_external : require From 47654a84c2dc68d478d044fd0589ec5cc96dbc66 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 7 Nov 2023 14:53:56 +0000 Subject: [PATCH 191/513] main: set isShuttingDown after display dispatch reaches the end relates to #3558 --- src/main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 9f8d61fc..40ddf390 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -104,6 +104,8 @@ int main(int argc, char** argv) { // If all's good to go, start. g_pCompositor->startCompositor(); + g_pCompositor->m_bIsShuttingDown = true; + // If we are here it means we got yote. Debug::log(LOG, "Hyprland reached the end."); g_pCompositor.reset(); From a0fcda301d4657db8eedcb88a348650fafab9896 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 7 Nov 2023 20:47:09 +0000 Subject: [PATCH 192/513] layout: round box in mouseMove fixes #3792 --- src/layout/IHyprLayout.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 274acb13..c5ed1199 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -305,11 +305,13 @@ void IHyprLayout::onMouseMove(const Vector2D& mousePos) { if (g_pInputManager->dragMode == MBIND_MOVE) { - if (*PANIMATEMOUSE) { - DRAGGINGWINDOW->m_vRealPosition = m_vBeginDragPositionXY + DELTA; - } else { - DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(m_vBeginDragPositionXY + DELTA); - } + CBox wb = {m_vBeginDragPositionXY + DELTA, DRAGGINGWINDOW->m_vRealSize.goalv()}; + wb.round(); + + if (*PANIMATEMOUSE) + DRAGGINGWINDOW->m_vRealPosition = wb.pos(); + else + DRAGGINGWINDOW->m_vRealPosition.setValueAndWarp(wb.pos()); g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, DRAGGINGWINDOW->m_vRealSize.goalv()); } else if (g_pInputManager->dragMode == MBIND_RESIZE || g_pInputManager->dragMode == MBIND_RESIZE_FORCE_RATIO || g_pInputManager->dragMode == MBIND_RESIZE_BLOCK_RATIO) { From 751d2851cc270c3322ffe2eb83c156e4298a0c0e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 7 Nov 2023 21:06:38 +0000 Subject: [PATCH 193/513] props: bump ver to 0.32.0 --- props.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/props.json b/props.json index d813a0c2..285025dd 100644 --- a/props.json +++ b/props.json @@ -1,3 +1,3 @@ { - "version": "0.31.0" + "version": "0.32.0" } \ No newline at end of file From c619e6976f8d7f9637b4bee098159935412c2e99 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 8 Nov 2023 12:43:07 +0000 Subject: [PATCH 194/513] screencopy: round boxes fixes #3795 --- src/protocols/Screencopy.cpp | 2 +- src/protocols/ToplevelExport.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 63ba8832..12170595 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -239,7 +239,7 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r } int ow, oh; wlr_output_effective_resolution(PFRAME->pMonitor->output, &ow, &oh); - PFRAME->box.transform(PFRAME->pMonitor->transform, ow, oh).scale(PFRAME->pMonitor->scale); + PFRAME->box.transform(PFRAME->pMonitor->transform, ow, oh).scale(PFRAME->pMonitor->scale).round(); PFRAME->shmStride = (PSHMINFO->bpp / 8) * PFRAME->box.width; diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 11287660..3f442781 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -201,7 +201,7 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou PFRAME->box = {0, 0, (int)(PFRAME->pWindow->m_vRealSize.vec().x * PMONITOR->scale), (int)(PFRAME->pWindow->m_vRealSize.vec().y * PMONITOR->scale)}; int ow, oh; wlr_output_effective_resolution(PMONITOR->output, &ow, &oh); - PFRAME->box.transform(PMONITOR->transform, ow, oh); + PFRAME->box.transform(PMONITOR->transform, ow, oh).round(); PFRAME->shmStride = (PSHMINFO->bpp / 8) * PFRAME->box.width; From da6fa9cbd24fb45edf35cc51317392e18f682595 Mon Sep 17 00:00:00 2001 From: Tobias Pisani Date: Thu, 9 Nov 2023 17:05:05 +0100 Subject: [PATCH 195/513] hyprctl: return group list in correct order (#3683) --- src/debug/HyprCtl.cpp | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index b274b244..c09251a8 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -105,27 +105,20 @@ static std::string getGroupedData(CWindow* w, HyprCtl::eHyprCtlOutputFormat form if (!w->m_sGroupData.pNextWindow) return isJson ? "" : "0"; - std::vector groupMembers; - - CWindow* curr = w; - do { - groupMembers.push_back(curr); - curr = curr->m_sGroupData.pNextWindow; - } while (curr != w); - - const auto comma = isJson ? ", " : ","; std::ostringstream result; - bool first = true; - for (auto& gw : groupMembers) { - if (first) - first = false; - else - result << comma; + CWindow* head = w->getGroupHead(); + CWindow* curr = head; + while (true) { if (isJson) - result << std::format("\"0x{:x}\"", (uintptr_t)gw); + result << std::format("\"0x{:x}\"", (uintptr_t)curr); else - result << std::format("{:x}", (uintptr_t)gw); + result << std::format("{:x}", (uintptr_t)curr); + curr = curr->m_sGroupData.pNextWindow; + // We've wrapped around to the start, break out without trailing comma + if (curr == head) + break; + result << (isJson ? ", " : ","); } return result.str(); From 11432f69b929b8f74d7b0a2b327cef1da2462535 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 9 Nov 2023 21:58:09 +0000 Subject: [PATCH 196/513] opengl: remove unused alpha matte from shadow --- src/render/OpenGL.cpp | 27 ++++++++++++--------------- src/render/shaders/Shadow.hpp | 7 ------- 2 files changed, 12 insertions(+), 22 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index e047f287..ab69295d 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -348,21 +348,18 @@ void CHyprOpenGLImpl::initShaders() { m_RenderData.pCurrentMonData->m_shBLURFINISH.brightness = glGetUniformLocation(prog, "brightness"); m_RenderData.pCurrentMonData->m_shBLURFINISH.noise = glGetUniformLocation(prog, "noise"); - prog = createProgram(QUADVERTSRC, FRAGSHADOW); - m_RenderData.pCurrentMonData->m_shSHADOW.program = prog; - m_RenderData.pCurrentMonData->m_shSHADOW.proj = glGetUniformLocation(prog, "proj"); - m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos"); - m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord"); - m_RenderData.pCurrentMonData->m_shSHADOW.matteTexAttrib = glGetAttribLocation(prog, "texcoordMatte"); - m_RenderData.pCurrentMonData->m_shSHADOW.alphaMatte = glGetUniformLocation(prog, "alphaMatte"); - m_RenderData.pCurrentMonData->m_shSHADOW.topLeft = glGetUniformLocation(prog, "topLeft"); - m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight"); - m_RenderData.pCurrentMonData->m_shSHADOW.fullSize = glGetUniformLocation(prog, "fullSize"); - m_RenderData.pCurrentMonData->m_shSHADOW.radius = glGetUniformLocation(prog, "radius"); - m_RenderData.pCurrentMonData->m_shSHADOW.range = glGetUniformLocation(prog, "range"); - m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower"); - m_RenderData.pCurrentMonData->m_shSHADOW.color = glGetUniformLocation(prog, "color"); - m_RenderData.pCurrentMonData->m_shSHADOW.useAlphaMatte = glGetUniformLocation(prog, "useAlphaMatte"); + prog = createProgram(QUADVERTSRC, FRAGSHADOW); + m_RenderData.pCurrentMonData->m_shSHADOW.program = prog; + m_RenderData.pCurrentMonData->m_shSHADOW.proj = glGetUniformLocation(prog, "proj"); + m_RenderData.pCurrentMonData->m_shSHADOW.posAttrib = glGetAttribLocation(prog, "pos"); + m_RenderData.pCurrentMonData->m_shSHADOW.texAttrib = glGetAttribLocation(prog, "texcoord"); + m_RenderData.pCurrentMonData->m_shSHADOW.topLeft = glGetUniformLocation(prog, "topLeft"); + m_RenderData.pCurrentMonData->m_shSHADOW.bottomRight = glGetUniformLocation(prog, "bottomRight"); + m_RenderData.pCurrentMonData->m_shSHADOW.fullSize = glGetUniformLocation(prog, "fullSize"); + m_RenderData.pCurrentMonData->m_shSHADOW.radius = glGetUniformLocation(prog, "radius"); + m_RenderData.pCurrentMonData->m_shSHADOW.range = glGetUniformLocation(prog, "range"); + m_RenderData.pCurrentMonData->m_shSHADOW.shadowPower = glGetUniformLocation(prog, "shadowPower"); + m_RenderData.pCurrentMonData->m_shSHADOW.color = glGetUniformLocation(prog, "color"); prog = createProgram(QUADVERTSRC, FRAGBORDER1); m_RenderData.pCurrentMonData->m_shBORDER1.program = prog; diff --git a/src/render/shaders/Shadow.hpp b/src/render/shaders/Shadow.hpp index f9bdeb8d..2c7b07b2 100644 --- a/src/render/shaders/Shadow.hpp +++ b/src/render/shaders/Shadow.hpp @@ -5,9 +5,7 @@ inline const std::string FRAGSHADOW = R"#( precision mediump float; varying vec4 v_color; -uniform sampler2D alphaMatte; varying vec2 v_texcoord; -varying vec2 v_texcoordMatte; uniform vec2 topLeft; uniform vec2 bottomRight; @@ -15,7 +13,6 @@ uniform vec2 fullSize; uniform float radius; uniform float range; uniform float shadowPower; -uniform int useAlphaMatte; float pixAlphaRoundedDistance(float distanceToCorner) { if (distanceToCorner > radius) { @@ -77,10 +74,6 @@ void main() { } } - if (useAlphaMatte == 1) { - pixColor[3] *= 1.0 - texture2D(alphaMatte, v_texcoordMatte)[3]; - } - if (pixColor[3] == 0.0) { discard; return; } From 14195835ef1dd25e10b0d873ec75c004b238ccba Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 9 Nov 2023 22:11:42 +0000 Subject: [PATCH 197/513] opengl: switch to black-and-white for alpha mattes also fixes shadows on 10b --- src/render/OpenGL.cpp | 4 ++-- src/render/OpenGL.hpp | 2 +- .../decorations/CHyprDropShadowDecoration.cpp | 19 +++++++++++++------ src/render/shaders/Textures.hpp | 2 +- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index ab69295d..26f3c128 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1718,7 +1718,7 @@ void CHyprOpenGLImpl::renderSnapshot(SLayerSurface** pLayer) { m_bEndFrame = false; } -void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, float a) { +void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const CColor& color, float a) { RASSERT(m_RenderData.pMonitor, "Tried to render shadow without begin()!"); RASSERT((box->width > 0 && box->height > 0), "Tried to render shadow with width/height < 0!"); RASSERT(m_pCurrentWindow, "Tried to render shadow without a window!"); @@ -1737,7 +1737,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, float const auto SHADOWPOWER = std::clamp((int)*PSHADOWPOWER, 1, 4); - const auto col = m_pCurrentWindow->m_cRealShadowColor.col(); + const auto col = color; float matrix[9]; wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 0c6ef13c..8c412302 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -113,7 +113,7 @@ class CHyprOpenGLImpl { void renderTexture(wlr_texture*, CBox*, float a, int round = 0, bool allowCustomUV = false); void renderTexture(const CTexture&, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); void renderTextureWithBlur(const CTexture&, CBox*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); - void renderRoundedShadow(CBox*, int round, int range, float a = 1.0); + void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0); void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); void renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte); diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 5341dec9..68a82c3a 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -140,19 +140,26 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D windowBox.addExtents(SWindowDecorationExtents{m_eLastExtents * pMonitor->scale}.floor()).round(); - if (windowBox.width < 1 || windowBox.height < 1) { + if (windowBox.width < 1 || windowBox.height < 1) return; // prevent assert failed - } alphaFB.bind(); - g_pHyprOpenGL->clear(CColor(0, 0, 0, 0)); - g_pHyprOpenGL->renderRect(&windowBox, CColor(1.0, 1.0, 1.0, 1.0), ROUNDING * pMonitor->scale); + // build the matte + // 10-bit formats have dogshit alpha channels, so we have to use the matte to its fullest. + // first, clear with black (fully transparent) + g_pHyprOpenGL->clear(CColor(0, 0, 0, 1)); + + // render white shadow + g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CColor(1, 1, 1, 1), a); + + // render black window box ("clip") + g_pHyprOpenGL->renderRect(&windowBox, CColor(0, 0, 0, 1.0), ROUNDING * pMonitor->scale); alphaSwapFB.bind(); - g_pHyprOpenGL->clear(CColor(0, 0, 0, 0)); - g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a); + // alpha swap just has the shadow color. It will be the "texture" to render. + g_pHyprOpenGL->clear(m_pWindow->m_cRealShadowColor.col()); LASTFB->bind(); diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index 15e80410..e0a2b498 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -137,7 +137,7 @@ uniform sampler2D tex; uniform sampler2D texMatte; void main() { - gl_FragColor = texture2D(tex, v_texcoord) * (1.0 - texture2D(texMatte, v_texcoord)[3]); + gl_FragColor = texture2D(tex, v_texcoord) * texture2D(texMatte, v_texcoord)[0]; // I know it only uses R, but matte should be black/white anyways. })#"; inline const std::string TEXFRAGSRCRGBX = R"#( From 8dd02eb5f3d47ce67a33c836ea6d648bd6967962 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 9 Nov 2023 22:43:52 +0000 Subject: [PATCH 198/513] xdg-shell: update reported size on ack_configure --- src/Window.hpp | 9 ++++++--- src/events/Events.hpp | 1 + src/events/Windows.cpp | 17 ++++++++++++++++- src/helpers/SubsurfaceTree.cpp | 5 ++--- src/layout/IHyprLayout.cpp | 4 +++- src/managers/XWaylandManager.cpp | 2 +- 6 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/Window.hpp b/src/Window.hpp index dbfa2e04..915cf018 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -185,6 +185,7 @@ class CWindow { DYNLISTENER(setOverrideRedirect); DYNLISTENER(associateX11); DYNLISTENER(dissociateX11); + DYNLISTENER(ackConfigure); // DYNLISTENER(newSubsurfaceWindow); CWLSurface m_pWLSurface; @@ -204,9 +205,11 @@ class CWindow { CAnimatedVariable m_vRealSize; // for not spamming the protocols - Vector2D m_vReportedPosition; - Vector2D m_vReportedSize; - Vector2D m_vPendingReportedSize; + Vector2D m_vReportedPosition; + Vector2D m_vReportedSize; + Vector2D m_vPendingReportedSize; + bool m_bPendingSizeAcked = false; + std::optional m_iPendingSizeAck; // for restoring floating statuses Vector2D m_vLastFloatingSize; diff --git a/src/events/Events.hpp b/src/events/Events.hpp index fc68880e..371586cc 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -62,6 +62,7 @@ namespace Events { DYNLISTENFUNC(setOverrideRedirect); DYNLISTENFUNC(associateX11); DYNLISTENFUNC(dissociateX11); + DYNLISTENFUNC(ackConfigure); // Window subsurfaces // LISTENER(newSubsurfaceWindow); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index f131efa4..1fbc9070 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -504,6 +504,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->hyprListener_requestResize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_resize, &Events::listener_requestResize, PWINDOW, "XDG Window Late"); PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW, "XDG Window Late"); + PWINDOW->hyprListener_ackConfigure.initCallback(&PWINDOW->m_uSurface.xdg->events.ack_configure, &Events::listener_ackConfigure, PWINDOW, "XDG Window Late"); } else { PWINDOW->hyprListener_fullscreenWindow.initCallback(&PWINDOW->m_uSurface.xwayland->events.request_fullscreen, &Events::listener_fullscreenWindow, PWINDOW, "XWayland Window Late"); @@ -682,6 +683,7 @@ void Events::listener_unmapWindow(void* owner, void* data) { PWINDOW->hyprListener_requestMove.removeCallback(); PWINDOW->hyprListener_requestResize.removeCallback(); PWINDOW->hyprListener_fullscreenWindow.removeCallback(); + PWINDOW->hyprListener_ackConfigure.removeCallback(); } else { Debug::log(LOG, "Unregistered late callbacks XWL"); PWINDOW->hyprListener_fullscreenWindow.removeCallback(); @@ -788,13 +790,26 @@ void Events::listener_unmapWindow(void* owner, void* data) { PWINDOW->onUnmap(); } +void Events::listener_ackConfigure(void* owner, void* data) { + CWindow* PWINDOW = (CWindow*)owner; + const auto E = (wlr_xdg_surface_configure*)data; + + if (!PWINDOW->m_iPendingSizeAck.has_value() || E->serial != PWINDOW->m_iPendingSizeAck) + return; + + PWINDOW->m_bPendingSizeAcked = true; + PWINDOW->m_iPendingSizeAck.reset(); +} + void Events::listener_commitWindow(void* owner, void* data) { CWindow* PWINDOW = (CWindow*)owner; if (!PWINDOW->m_bMappedX11 || PWINDOW->isHidden() || (PWINDOW->m_bIsX11 && !PWINDOW->m_bMappedX11)) return; - PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged. + if (PWINDOW->m_bIsX11 || PWINDOW->m_bPendingSizeAcked) + PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged. + PWINDOW->m_bPendingSizeAcked = false; PWINDOW->updateSurfaceOutputs(); diff --git a/src/helpers/SubsurfaceTree.cpp b/src/helpers/SubsurfaceTree.cpp index 84ba5cbb..c10d45e1 100644 --- a/src/helpers/SubsurfaceTree.cpp +++ b/src/helpers/SubsurfaceTree.cpp @@ -248,14 +248,13 @@ void Events::listener_commitSubsurface(void* owner, void* data) { g_pHyprRenderer->damageSurface(pNode->pSurface->wlr(), lx, ly, SCALE); if (pNode->pWindowOwner) { - // update reported size. Some windows do not send a ::commit afterwards. Odd. - pNode->pWindowOwner->m_vReportedSize = pNode->pWindowOwner->m_vPendingReportedSize; + if (pNode->pWindowOwner->m_bIsX11) + pNode->pWindowOwner->m_vReportedSize = pNode->pWindowOwner->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged. // tearing: if solitary, redraw it. This still might be a single surface window const auto PMONITOR = g_pCompositor->getMonitorFromID(pNode->pWindowOwner->m_iMonitorID); if (PMONITOR->solitaryClient == pNode->pWindowOwner && pNode->pWindowOwner->canBeTorn() && PMONITOR->tearingState.canTear && pNode->pSurface->wlr()->current.committed & WLR_SURFACE_STATE_BUFFER) { - CRegion damageBox; wlr_surface_get_effective_damage(pNode->pSurface->wlr(), damageBox.pixman()); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index c5ed1199..abc1aeda 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -162,8 +162,10 @@ void IHyprLayout::onWindowCreatedFloating(CWindow* pWindow) { g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv()); g_pCompositor->changeWindowZOrder(pWindow, true); - } else + } else { pWindow->m_vPendingReportedSize = pWindow->m_vRealSize.goalv(); + pWindow->m_vReportedSize = pWindow->m_vPendingReportedSize; + } } void IHyprLayout::onBeginDragWindow() { diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 04fbaf21..f9d57a3f 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -180,7 +180,7 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f if (pWindow->m_bIsX11) wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, windowPos.x, windowPos.y, size.x, size.y); else - wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y); + pWindow->m_iPendingSizeAck = wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y); } void CHyprXWaylandManager::setWindowStyleTiled(CWindow* pWindow, uint32_t edgez) { From b8a615ffb892aaa35a15dc732208bb7ad2a60209 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 10 Nov 2023 00:13:22 +0000 Subject: [PATCH 199/513] xdg-shell: improve ack-configure handling fixes #3807 --- src/Window.hpp | 10 +++++----- src/events/Windows.cpp | 16 +++++++++++----- src/managers/XWaylandManager.cpp | 4 ++-- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/Window.hpp b/src/Window.hpp index 915cf018..580b0a2a 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -205,11 +205,11 @@ class CWindow { CAnimatedVariable m_vRealSize; // for not spamming the protocols - Vector2D m_vReportedPosition; - Vector2D m_vReportedSize; - Vector2D m_vPendingReportedSize; - bool m_bPendingSizeAcked = false; - std::optional m_iPendingSizeAck; + Vector2D m_vReportedPosition; + Vector2D m_vReportedSize; + Vector2D m_vPendingReportedSize; + std::optional> m_pPendingSizeAck; + std::vector> m_vPendingSizeAcks; // for restoring floating statuses Vector2D m_vLastFloatingSize; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 1fbc9070..e44fa0a9 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -794,11 +794,14 @@ void Events::listener_ackConfigure(void* owner, void* data) { CWindow* PWINDOW = (CWindow*)owner; const auto E = (wlr_xdg_surface_configure*)data; - if (!PWINDOW->m_iPendingSizeAck.has_value() || E->serial != PWINDOW->m_iPendingSizeAck) + // find last matching serial + const auto SERIAL = std::find_if(PWINDOW->m_vPendingSizeAcks.rbegin(), PWINDOW->m_vPendingSizeAcks.rend(), [&](const auto& e) { return e.first == E->serial; }); + + if (SERIAL == PWINDOW->m_vPendingSizeAcks.rend()) return; - PWINDOW->m_bPendingSizeAcked = true; - PWINDOW->m_iPendingSizeAck.reset(); + PWINDOW->m_pPendingSizeAck = *SERIAL; + std::erase_if(PWINDOW->m_vPendingSizeAcks, [&](const auto& el) { return el.first == SERIAL->first; }); } void Events::listener_commitWindow(void* owner, void* data) { @@ -807,9 +810,12 @@ void Events::listener_commitWindow(void* owner, void* data) { if (!PWINDOW->m_bMappedX11 || PWINDOW->isHidden() || (PWINDOW->m_bIsX11 && !PWINDOW->m_bMappedX11)) return; - if (PWINDOW->m_bIsX11 || PWINDOW->m_bPendingSizeAcked) + if (PWINDOW->m_bIsX11) PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged. - PWINDOW->m_bPendingSizeAcked = false; + else if (PWINDOW->m_pPendingSizeAck.has_value()) { + PWINDOW->m_vReportedSize = PWINDOW->m_pPendingSizeAck->second; + PWINDOW->m_pPendingSizeAck.reset(); + } PWINDOW->updateSurfaceOutputs(); diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index f9d57a3f..04fcf967 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -162,7 +162,7 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f windowPos = windowPos + PMONITOR->vecXWaylandPosition; // move to correct position for xwayland } - if (!force && ((pWindow->m_vReportedSize == size && windowPos == pWindow->m_vReportedPosition) || (pWindow->m_vReportedSize == size && !pWindow->m_bIsX11))) + if (!force && ((pWindow->m_vPendingReportedSize == size && windowPos == pWindow->m_vReportedPosition) || (pWindow->m_vPendingReportedSize == size && !pWindow->m_bIsX11))) return; pWindow->m_vReportedPosition = windowPos; @@ -180,7 +180,7 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f if (pWindow->m_bIsX11) wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, windowPos.x, windowPos.y, size.x, size.y); else - pWindow->m_iPendingSizeAck = wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y); + pWindow->m_vPendingSizeAcks.push_back(std::make_pair<>(wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y), size.floor())); } void CHyprXWaylandManager::setWindowStyleTiled(CWindow* pWindow, uint32_t edgez) { From 92cb44ddb2b464d1ef770ba1f4c79eafecae065b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 10 Nov 2023 18:49:15 +0000 Subject: [PATCH 200/513] input: don't schedule repaint on cursor move if hardware cursors are in use --- src/managers/input/InputManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index d7733e96..78ed3d71 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -112,7 +112,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (*PZOOMFACTOR != 1.f) g_pHyprRenderer->damageMonitor(PMONITOR); - if (!PMONITOR->solitaryClient && g_pHyprRenderer->shouldRenderCursor()) + if (!PMONITOR->solitaryClient && g_pHyprRenderer->shouldRenderCursor() && PMONITOR->output->software_cursor_locks > 0) g_pCompositor->scheduleFrameForMonitor(PMONITOR); CWindow* forcedFocus = m_pForcedFocus; From 1e6e9b66a5837d62d374edd405bdf561813ebbce Mon Sep 17 00:00:00 2001 From: Greatly Pleased Date: Fri, 10 Nov 2023 22:45:20 +0100 Subject: [PATCH 201/513] hyprctl: Fix build warnings (#3821) --- hyprctl/main.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 77dd0d58..c05b5201 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -274,7 +274,6 @@ bool isNumber(const std::string& str, bool allowfloat) { } int main(int argc, char** argv) { - int bflag = 0, sflag = 0, index, c; bool parseArgs = true; if (argc < 2) { @@ -288,7 +287,7 @@ int main(int argc, char** argv) { bool json = false; std::string overrideInstance = ""; - for (auto i = 0; i < ARGS.size(); ++i) { + for (std::size_t i = 0; i < ARGS.size(); ++i) { if (ARGS[i] == "--") { // Stop parsing arguments after -- parseArgs = false; @@ -342,7 +341,7 @@ int main(int argc, char** argv) { const auto INSTANCES = instances(); - if (INSTANCENO < 0 || INSTANCENO >= INSTANCES.size()) { + if (INSTANCENO < 0 || static_cast(INSTANCENO) >= INSTANCES.size()) { std::cout << "no such instance\n"; return 1; } From 427153e86ad7070ea0e4d39f7fd348b8f720e055 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 10 Nov 2023 23:49:23 +0000 Subject: [PATCH 202/513] xwayland: add half of delta to configure request sizes --- src/events/Windows.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index e44fa0a9..c6c9024e 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -1059,8 +1059,11 @@ void Events::listener_configureX11(void* owner, void* data) { static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue; if (*PXWLFORCESCALEZERO) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) + if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) { + const Vector2D DELTA = PWINDOW->m_vRealSize.goalv() - PWINDOW->m_vRealSize.goalv() / PMONITOR->scale; PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale); + PWINDOW->m_vRealPosition.setValueAndWarp(PWINDOW->m_vRealPosition.goalv() + DELTA / 2.0); + } } PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.vec(); @@ -1120,8 +1123,11 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) { PWINDOW->m_vRealSize.setValueAndWarp(Vector2D(PWINDOW->m_uSurface.xwayland->width, PWINDOW->m_uSurface.xwayland->height)); if (*PXWLFORCESCALEZERO) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) + if (const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); PMONITOR) { + const Vector2D DELTA = PWINDOW->m_vRealSize.goalv() - PWINDOW->m_vRealSize.goalv() / PMONITOR->scale; PWINDOW->m_vRealSize.setValueAndWarp(PWINDOW->m_vRealSize.goalv() / PMONITOR->scale); + PWINDOW->m_vRealPosition.setValueAndWarp(PWINDOW->m_vRealPosition.goalv() + DELTA / 2.0); + } } PWINDOW->m_vPosition = PWINDOW->m_vRealPosition.goalv(); From e44d6de555da72bd45ebd01c1293d53ea2700d3f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 11 Nov 2023 00:52:40 +0000 Subject: [PATCH 203/513] shadow: alpha treatment improvements --- src/helpers/Color.hpp | 6 +++++- src/render/decorations/CHyprDropShadowDecoration.cpp | 6 +++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/helpers/Color.hpp b/src/helpers/Color.hpp index ffd6d2d8..98ffa476 100644 --- a/src/helpers/Color.hpp +++ b/src/helpers/Color.hpp @@ -5,7 +5,7 @@ class CColor { public: CColor(); - CColor(float, float, float, float); + CColor(float r, float g, float b, float a); CColor(uint64_t); float r = 0, g = 0, b = 0, a = 1.f; @@ -27,4 +27,8 @@ class CColor { bool operator==(const CColor& c2) const { return r == c2.r && g == c2.g && b == c2.b && a == c2.a; } + + CColor stripA() const { + return {r, g, b, 1}; + } }; diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 68a82c3a..ac6c5b43 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -150,8 +150,8 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D // first, clear with black (fully transparent) g_pHyprOpenGL->clear(CColor(0, 0, 0, 1)); - // render white shadow - g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CColor(1, 1, 1, 1), a); + // render white shadow with the alpha of the shadow color (otherwise we clear with alpha later and shit it to 2 bit) + g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CColor(1, 1, 1, m_pWindow->m_cRealShadowColor.col().a), a); // render black window box ("clip") g_pHyprOpenGL->renderRect(&windowBox, CColor(0, 0, 0, 1.0), ROUNDING * pMonitor->scale); @@ -159,7 +159,7 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D alphaSwapFB.bind(); // alpha swap just has the shadow color. It will be the "texture" to render. - g_pHyprOpenGL->clear(m_pWindow->m_cRealShadowColor.col()); + g_pHyprOpenGL->clear(m_pWindow->m_cRealShadowColor.col().stripA()); LASTFB->bind(); From 7345b1a1ea2671953df48c8a18524a7e556d383c Mon Sep 17 00:00:00 2001 From: Dickby Date: Sat, 11 Nov 2023 14:15:37 +0100 Subject: [PATCH 204/513] shaders: Use clamp in doubleCircleSigmoid. (#3824) --- src/render/shaders/Textures.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index e0a2b498..daa7bc9b 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -205,9 +205,7 @@ const float c = 0.66; // Determines the smoothness of the transition of unboost // http://www.flong.com/archive/texts/code/shapers_circ/ float doubleCircleSigmoid(float x, float a) { - float min_param_a = 0.0; - float max_param_a = 1.0; - a = max(min_param_a, min(max_param_a, a)); + a = clamp(a, 0.0, 1.0); float y = .0; if (x <= a) { From 9be6fbf5eae8c4b902b818881a4dc34f87bb630d Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sat, 11 Nov 2023 14:37:17 +0000 Subject: [PATCH 205/513] decorations: Decoration Positioner (#3800) --- src/Compositor.cpp | 7 +- src/SharedDefs.hpp | 4 +- src/Window.cpp | 92 +++--- src/Window.hpp | 2 + src/helpers/Box.cpp | 13 + src/helpers/Box.hpp | 35 ++- src/helpers/Region.cpp | 9 +- src/helpers/Region.hpp | 3 +- src/helpers/Vector2D.cpp | 4 + src/helpers/Vector2D.hpp | 1 + src/layout/DwindleLayout.cpp | 8 +- src/layout/MasterLayout.cpp | 8 +- src/managers/AnimationManager.cpp | 23 +- src/managers/KeybindManager.cpp | 8 +- src/managers/input/InputManager.cpp | 6 +- src/plugins/PluginAPI.cpp | 9 +- src/plugins/PluginAPI.hpp | 2 +- src/render/OpenGL.cpp | 4 +- src/render/Renderer.cpp | 2 +- .../decorations/CHyprDropShadowDecoration.cpp | 66 ++--- .../decorations/CHyprDropShadowDecoration.hpp | 18 +- .../decorations/CHyprGroupBarDecoration.cpp | 105 ++++--- .../decorations/CHyprGroupBarDecoration.hpp | 29 +- .../decorations/DecorationPositioner.cpp | 277 ++++++++++++++++++ .../decorations/DecorationPositioner.hpp | 96 ++++++ .../decorations/IHyprWindowDecoration.cpp | 17 -- .../decorations/IHyprWindowDecoration.hpp | 28 +- 27 files changed, 610 insertions(+), 266 deletions(-) create mode 100644 src/render/decorations/DecorationPositioner.cpp create mode 100644 src/render/decorations/DecorationPositioner.hpp diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 30e9fdb6..29d019c1 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -81,6 +81,7 @@ CCompositor::CCompositor() { CCompositor::~CCompositor() { cleanup(); + g_pDecorationPositioner.reset(); g_pPluginSystem.reset(); g_pHyprNotificationOverlay.reset(); g_pDebugOverlay.reset(); @@ -441,6 +442,9 @@ void CCompositor::initManagers(eManagersInitStage stage) { Debug::log(LOG, "Creating the PluginSystem!"); g_pPluginSystem = std::make_unique(); g_pConfigManager->handlePluginLoads(); + + Debug::log(LOG, "Creating the DecorationPositioner!"); + g_pDecorationPositioner = std::make_unique(); } break; default: UNREACHABLE(); } @@ -1920,8 +1924,7 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) { pWindow->m_cRealShadowColor.setValueAndWarp(CColor(0, 0, 0, 0)); // no shadow } - for (auto& d : pWindow->m_dWindowDecorations) - d->updateWindow(pWindow); + pWindow->updateWindowDecos(); } int CCompositor::getNextAvailableMonitorID(std::string const& name) { diff --git a/src/SharedDefs.hpp b/src/SharedDefs.hpp index fb99caaa..4e4217d2 100644 --- a/src/SharedDefs.hpp +++ b/src/SharedDefs.hpp @@ -39,7 +39,7 @@ struct SWindowDecorationExtents { return SWindowDecorationExtents{topLeft * scale, bottomRight * scale}; } - SWindowDecorationExtents floor() { - return {topLeft.floor(), bottomRight.floor()}; + SWindowDecorationExtents round() { + return {topLeft.round(), bottomRight.round()}; } }; \ No newline at end of file diff --git a/src/Window.cpp b/src/Window.cpp index 7994b6cb..c1b79c2d 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -13,7 +13,7 @@ CWindow::CWindow() { m_cRealShadowColor.create(AVARTYPE_COLOR, g_pConfigManager->getAnimationPropertyConfig("fadeShadow"), (void*)this, AVARDAMAGE_SHADOW); m_fDimPercent.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), (void*)this, AVARDAMAGE_ENTIRE); - m_dWindowDecorations.emplace_back(std::make_unique(this)); // put the shadow so it's the first deco (has to be rendered first) + addWindowDeco(std::make_unique(this)); } CWindow::~CWindow() { @@ -37,22 +37,19 @@ SWindowDecorationExtents CWindow::getFullWindowExtents() { SWindowDecorationExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}}; - for (auto& wd : m_dWindowDecorations) { + const auto EXTENTS = g_pDecorationPositioner->getWindowDecorationExtents(this); - const auto EXTENTS = wd->getWindowDecorationExtents(); + if (EXTENTS.topLeft.x > maxExtents.topLeft.x) + maxExtents.topLeft.x = EXTENTS.topLeft.x; - if (EXTENTS.topLeft.x > maxExtents.topLeft.x) - maxExtents.topLeft.x = EXTENTS.topLeft.x; + if (EXTENTS.topLeft.y > maxExtents.topLeft.y) + maxExtents.topLeft.y = EXTENTS.topLeft.y; - if (EXTENTS.topLeft.y > maxExtents.topLeft.y) - maxExtents.topLeft.y = EXTENTS.topLeft.y; + if (EXTENTS.bottomRight.x > maxExtents.bottomRight.x) + maxExtents.bottomRight.x = EXTENTS.bottomRight.x; - if (EXTENTS.bottomRight.x > maxExtents.bottomRight.x) - maxExtents.bottomRight.x = EXTENTS.bottomRight.x; - - if (EXTENTS.bottomRight.y > maxExtents.bottomRight.y) - maxExtents.bottomRight.y = EXTENTS.bottomRight.y; - } + if (EXTENTS.bottomRight.y > maxExtents.bottomRight.y) + maxExtents.bottomRight.y = EXTENTS.bottomRight.y; if (m_pWLSurface.exists() && !m_bIsX11) { CBox surfaceExtents = {0, 0, 0, 0}; @@ -144,25 +141,19 @@ CBox CWindow::getWindowInputBox() { SWindowDecorationExtents maxExtents = {{BORDERSIZE + 2, BORDERSIZE + 2}, {BORDERSIZE + 2, BORDERSIZE + 2}}; - for (auto& wd : m_dWindowDecorations) { + const auto EXTENTS = g_pDecorationPositioner->getWindowDecorationExtents(this, true); - if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) - continue; + if (EXTENTS.topLeft.x > maxExtents.topLeft.x) + maxExtents.topLeft.x = EXTENTS.topLeft.x; - const auto EXTENTS = wd->getWindowDecorationExtents(); + if (EXTENTS.topLeft.y > maxExtents.topLeft.y) + maxExtents.topLeft.y = EXTENTS.topLeft.y; - if (EXTENTS.topLeft.x > maxExtents.topLeft.x) - maxExtents.topLeft.x = EXTENTS.topLeft.x; + if (EXTENTS.bottomRight.x > maxExtents.bottomRight.x) + maxExtents.bottomRight.x = EXTENTS.bottomRight.x; - if (EXTENTS.topLeft.y > maxExtents.topLeft.y) - maxExtents.topLeft.y = EXTENTS.topLeft.y; - - if (EXTENTS.bottomRight.x > maxExtents.bottomRight.x) - maxExtents.bottomRight.x = EXTENTS.bottomRight.x; - - if (EXTENTS.bottomRight.y > maxExtents.bottomRight.y) - maxExtents.bottomRight.y = EXTENTS.bottomRight.y; - } + if (EXTENTS.bottomRight.y > maxExtents.bottomRight.y) + maxExtents.bottomRight.y = EXTENTS.bottomRight.y; // Add extents to the real base BB and return CBox finalBox = {m_vRealPosition.vec().x - maxExtents.topLeft.x, m_vRealPosition.vec().y - maxExtents.topLeft.y, @@ -176,30 +167,19 @@ CBox CWindow::getWindowMainSurfaceBox() { } SWindowDecorationExtents CWindow::getFullWindowReservedArea() { - SWindowDecorationExtents extents; - - for (auto& wd : m_dWindowDecorations) { - const auto RESERVED = wd->getWindowDecorationReservedArea(); - - if (RESERVED.bottomRight == Vector2D{} && RESERVED.topLeft == Vector2D{}) - continue; - - extents.topLeft = extents.topLeft + RESERVED.topLeft; - extents.bottomRight = extents.bottomRight + RESERVED.bottomRight; - } - - return extents; + return g_pDecorationPositioner->getWindowDecorationReserved(this); } void CWindow::updateWindowDecos() { - for (auto& wd : m_dWindowDecorations) - wd->updateWindow(this); - bool recalc = false; + if (!m_bIsMapped || isHidden()) + return; + for (auto& wd : m_vDecosToRemove) { for (auto it = m_dWindowDecorations.begin(); it != m_dWindowDecorations.end(); it++) { if (it->get() == wd) { + g_pDecorationPositioner->uncacheDecoration(it->get()); it = m_dWindowDecorations.erase(it); recalc = true; if (it == m_dWindowDecorations.end()) @@ -208,10 +188,26 @@ void CWindow::updateWindowDecos() { } } + g_pDecorationPositioner->onWindowUpdate(this); + if (recalc) g_pLayoutManager->getCurrentLayout()->recalculateWindow(this); m_vDecosToRemove.clear(); + + for (auto& wd : m_dWindowDecorations) { + wd->updateWindow(this); + } +} + +void CWindow::addWindowDeco(std::unique_ptr deco) { + m_dWindowDecorations.emplace_back(std::move(deco)); + updateWindowDecos(); +} + +void CWindow::removeWindowDeco(IHyprWindowDecoration* deco) { + m_vDecosToRemove.push_back(deco); + updateWindowDecos(); } pid_t CWindow::getPID() { @@ -689,14 +685,14 @@ void CWindow::createGroup() { Debug::log(LOG, "createGroup: window:{:x},title:{} is denied as a group, ignored", (uintptr_t)this, this->m_szTitle); return; } + if (!m_sGroupData.pNextWindow) { m_sGroupData.pNextWindow = this; m_sGroupData.head = true; m_sGroupData.locked = false; m_sGroupData.deny = false; - m_dWindowDecorations.emplace_back(std::make_unique(this)); - updateWindowDecos(); + addWindowDeco(std::make_unique(this)); g_pLayoutManager->getCurrentLayout()->recalculateWindow(this); g_pCompositor->updateAllWindowsAnimatedDecorationValues(); @@ -835,6 +831,8 @@ void CWindow::setGroupCurrent(CWindow* pWindow) { g_pCompositor->setWindowFullscreen(pWindow, true, WORKSPACE->m_efFullscreenMode); g_pHyprRenderer->damageWindow(pWindow); + + pWindow->updateWindowDecos(); } void CWindow::insertWindowToGroup(CWindow* pWindow) { @@ -842,7 +840,7 @@ void CWindow::insertWindowToGroup(CWindow* pWindow) { const auto ENDAT = m_sGroupData.pNextWindow; if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) - pWindow->m_dWindowDecorations.emplace_back(std::make_unique(pWindow)); + pWindow->addWindowDeco(std::make_unique(pWindow)); if (!pWindow->m_sGroupData.pNextWindow) { BEGINAT->m_sGroupData.pNextWindow = pWindow; diff --git a/src/Window.hpp b/src/Window.hpp index 580b0a2a..4e1ab9c1 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -344,7 +344,9 @@ class CWindow { CBox getWindowInputBox(); CBox getWindowMainSurfaceBox(); CBox getWindowIdealBoundingBoxIgnoreReserved(); + void addWindowDeco(std::unique_ptr deco); void updateWindowDecos(); + void removeWindowDeco(IHyprWindowDecoration* deco); pid_t getPID(); IHyprWindowDecoration* getDecorationByType(eDecorationType); void removeDecorationByType(eDecorationType); diff --git a/src/helpers/Box.cpp b/src/helpers/Box.cpp index 55300f5f..29aa81fa 100644 --- a/src/helpers/Box.cpp +++ b/src/helpers/Box.cpp @@ -96,6 +96,15 @@ CBox& CBox::scaleFromCenter(double scale) { return *this; } +CBox& CBox::expand(const double& value) { + x -= value; + y -= value; + w += value * 2.0; + h += value * 2.0; + + return *this; +} + CBox CBox::roundInternal() { float newW = x + w - std::floor(x); float newH = y + h - std::floor(y); @@ -110,3 +119,7 @@ Vector2D CBox::pos() const { Vector2D CBox::size() const { return {w, h}; } + +SWindowDecorationExtents CBox::extentsFrom(const CBox& small) { + return {{small.x - x, small.y - y}, {w - small.w - (small.x - x), h - small.h - (small.y - y)}}; +} diff --git a/src/helpers/Box.hpp b/src/helpers/Box.hpp index 592bb417..cb07df06 100644 --- a/src/helpers/Box.hpp +++ b/src/helpers/Box.hpp @@ -39,26 +39,29 @@ class CBox { h = size.y; } - wlr_box wlr(); - wlr_box* pWlr(); + wlr_box wlr(); + wlr_box* pWlr(); - CBox& applyFromWlr(); - CBox& scale(double scale); - CBox& scaleFromCenter(double scale); - CBox& scale(const Vector2D& scale); - CBox& translate(const Vector2D& vec); - CBox& round(); - CBox& transform(const wl_output_transform t, double w, double h); - CBox& addExtents(const SWindowDecorationExtents& e); + CBox& applyFromWlr(); + CBox& scale(double scale); + CBox& scaleFromCenter(double scale); + CBox& scale(const Vector2D& scale); + CBox& translate(const Vector2D& vec); + CBox& round(); + CBox& transform(const wl_output_transform t, double w, double h); + CBox& addExtents(const SWindowDecorationExtents& e); + CBox& expand(const double& value); - Vector2D middle() const; - Vector2D pos() const; - Vector2D size() const; + SWindowDecorationExtents extentsFrom(const CBox&); // this is the big box - bool containsPoint(const Vector2D& vec) const; - bool empty() const; + Vector2D middle() const; + Vector2D pos() const; + Vector2D size() const; - double x = 0, y = 0; + bool containsPoint(const Vector2D& vec) const; + bool empty() const; + + double x = 0, y = 0; union { double w; double width; diff --git a/src/helpers/Region.cpp b/src/helpers/Region.cpp index fdf8a242..06b8536c 100644 --- a/src/helpers/Region.cpp +++ b/src/helpers/Region.cpp @@ -21,8 +21,8 @@ CRegion::CRegion(wlr_box* box) { pixman_region32_init_rect(&m_rRegion, box->x, box->y, box->width, box->height); } -CRegion::CRegion(CBox* box) { - pixman_region32_init_rect(&m_rRegion, box->x, box->y, box->w, box->h); +CRegion::CRegion(const CBox& box) { + pixman_region32_init_rect(&m_rRegion, box.x, box.y, box.w, box.h); } CRegion::CRegion(pixman_box32_t* box) { @@ -63,6 +63,11 @@ CRegion& CRegion::add(double x, double y, double w, double h) { return *this; } +CRegion& CRegion::add(const CBox& other) { + pixman_region32_union_rect(&m_rRegion, &m_rRegion, other.x, other.y, other.w, other.h); + return *this; +} + CRegion& CRegion::subtract(const CRegion& other) { pixman_region32_subtract(&m_rRegion, &m_rRegion, const_cast(&other)->pixman()); return *this; diff --git a/src/helpers/Region.hpp b/src/helpers/Region.hpp index 80153cff..1c6923df 100644 --- a/src/helpers/Region.hpp +++ b/src/helpers/Region.hpp @@ -17,7 +17,7 @@ class CRegion { /* Create from a wlr_box */ CRegion(wlr_box* box); /* Create from a CBox */ - CRegion(CBox* box); + CRegion(const CBox& box); /* Create from a pixman_box32_t */ CRegion(pixman_box32_t* box); @@ -40,6 +40,7 @@ class CRegion { CRegion& set(const CRegion& other); CRegion& add(const CRegion& other); CRegion& add(double x, double y, double w, double h); + CRegion& add(const CBox& other); CRegion& subtract(const CRegion& other); CRegion& intersect(const CRegion& other); CRegion& intersect(double x, double y, double w, double h); diff --git a/src/helpers/Vector2D.cpp b/src/helpers/Vector2D.cpp index ae2484b3..7bc6412d 100644 --- a/src/helpers/Vector2D.cpp +++ b/src/helpers/Vector2D.cpp @@ -28,6 +28,10 @@ Vector2D Vector2D::floor() const { return Vector2D(std::floor(x), std::floor(y)); } +Vector2D Vector2D::round() const { + return Vector2D(std::round(x), std::round(y)); +} + Vector2D Vector2D::clamp(const Vector2D& min, const Vector2D& max) const { return Vector2D(std::clamp(this->x, min.x, max.x < min.x ? INFINITY : max.x), std::clamp(this->y, min.y, max.y < min.y ? INFINITY : max.y)); } diff --git a/src/helpers/Vector2D.hpp b/src/helpers/Vector2D.hpp index 17415289..c79c967c 100644 --- a/src/helpers/Vector2D.hpp +++ b/src/helpers/Vector2D.hpp @@ -61,6 +61,7 @@ class Vector2D { Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D()) const; Vector2D floor() const; + Vector2D round() const; bool inTriangle(const Vector2D& p1, const Vector2D& p2, const Vector2D& p3) const; }; diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 6602c758..a01c3b8c 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -323,7 +323,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) continue; - if (wd->getWindowDecorationRegion().containsPoint(MOUSECOORDS)) { + if (g_pDecorationPositioner->getWindowDecorationBox(wd.get()).containsPoint(MOUSECOORDS)) { if (!wd->onEndWindowDragOnDeco(pWindow, MOUSECOORDS)) return; break; @@ -334,9 +334,6 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire // if it's a group, add the window if (OPENINGON->pWindow->m_sGroupData.pNextWindow // target is group && pWindow->canBeGroupedInto(OPENINGON->pWindow) && !m_vOverrideFocalPoint) { // we are not moving window - if (!pWindow->m_sGroupData.pNextWindow) - pWindow->m_dWindowDecorations.emplace_back(std::make_unique(pWindow)); - m_lDwindleNodesData.remove(*PNODE); static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue; @@ -347,6 +344,9 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire pWindow->updateWindowDecos(); recalculateWindow(pWindow); + if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) + pWindow->addWindowDeco(std::make_unique(pWindow)); + return; } diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 57784786..d355a7d3 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -99,7 +99,7 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) continue; - if (wd->getWindowDecorationRegion().containsPoint(MOUSECOORDS)) { + if (g_pDecorationPositioner->getWindowDecorationBox(wd.get()).containsPoint(MOUSECOORDS)) { if (!wd->onEndWindowDragOnDeco(pWindow, MOUSECOORDS)) return; break; @@ -111,9 +111,6 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc if (OPENINGON && OPENINGON != PNODE && OPENINGON->pWindow->m_sGroupData.pNextWindow // target is group && pWindow->canBeGroupedInto(OPENINGON->pWindow)) { - if (!pWindow->m_sGroupData.pNextWindow) - pWindow->m_dWindowDecorations.emplace_back(std::make_unique(pWindow)); - m_lMasterNodesData.remove(*PNODE); static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue; @@ -124,6 +121,9 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc pWindow->updateWindowDecos(); recalculateWindow(pWindow); + if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) + pWindow->addWindowDeco(std::make_unique(pWindow)); + return; } diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 1dc8e2c6..a5e1c47e 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -248,28 +248,9 @@ void CAnimationManager::tick() { case AVARDAMAGE_SHADOW: { RASSERT(PWINDOW, "Tried to AVARDAMAGE_SHADOW a non-window AVAR!"); - static auto* const PSHADOWIGNOREWINDOW = &g_pConfigManager->getConfigValuePtr("decoration:shadow_ignore_window")->intValue; + const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW); - const auto PDECO = PWINDOW->getDecorationByType(DECORATION_SHADOW); - - if (PDECO) { - const auto EXTENTS = PDECO->getWindowDecorationExtents(); - - CBox dmg = {PWINDOW->m_vRealPosition.vec().x - EXTENTS.topLeft.x, PWINDOW->m_vRealPosition.vec().y - EXTENTS.topLeft.y, - PWINDOW->m_vRealSize.vec().x + EXTENTS.topLeft.x + EXTENTS.bottomRight.x, PWINDOW->m_vRealSize.vec().y + EXTENTS.topLeft.y + EXTENTS.bottomRight.y}; - - if (!*PSHADOWIGNOREWINDOW) { - // easy, damage the entire box - g_pHyprRenderer->damageBox(&dmg); - } else { - CRegion rg{dmg.x, dmg.y, dmg.width, dmg.height}; - CRegion wb{PWINDOW->m_vRealPosition.vec().x, PWINDOW->m_vRealPosition.vec().y, PWINDOW->m_vRealSize.vec().x, PWINDOW->m_vRealSize.vec().y}; - - rg.subtract(wb); - - g_pHyprRenderer->damageRegion(rg); - } - } + PDECO->damageEntire(); break; } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 3bed027d..e4cac5f4 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1845,7 +1845,7 @@ void CKeybindManager::mouse(std::string args) { if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) continue; - if (wd->getWindowDecorationRegion().containsPoint(mouseCoords)) { + if (g_pDecorationPositioner->getWindowDecorationBox(wd.get()).containsPoint(mouseCoords)) { wd->onBeginWindowDragOnDeco(mouseCoords); break; } @@ -1964,9 +1964,6 @@ void CKeybindManager::moveWindowIntoGroup(CWindow* pWindow, CWindow* pWindowInDi if (pWindow->m_sGroupData.deny) return; - if (!pWindow->m_sGroupData.pNextWindow) - pWindow->m_dWindowDecorations.emplace_back(std::make_unique(pWindow)); - g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow); // This removes groupped property! static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue; @@ -1978,6 +1975,9 @@ void CKeybindManager::moveWindowIntoGroup(CWindow* pWindow, CWindow* pWindowInDi g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow); g_pCompositor->focusWindow(pWindow); g_pCompositor->warpCursorTo(pWindow->middle()); + + if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) + pWindow->addWindowDeco(std::make_unique(pWindow)); } void CKeybindManager::moveWindowOutOfGroup(CWindow* pWindow, const std::string& dir) { diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 78ed3d71..d096ab32 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -588,7 +588,7 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) continue; - if (wd->getWindowDecorationRegion().containsPoint(mouseCoords)) { + if (g_pDecorationPositioner->getWindowDecorationBox(wd.get()).containsPoint(mouseCoords)) { wd->onMouseButtonOnDeco(mouseCoords, e); return; } @@ -675,7 +675,7 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) { const auto pWindow = g_pCompositor->vectorToWindowIdeal(MOUSECOORDS); if (*PGROUPBARSCROLLING && pWindow && !pWindow->m_bIsFullscreen && !pWindow->hasPopupAt(MOUSECOORDS) && pWindow->m_sGroupData.pNextWindow) { - const CBox box = pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents(); + const CBox box = g_pDecorationPositioner->getWindowDecorationBox(pWindow->getDecorationByType(DECORATION_GROUPBAR)); if (box.containsPoint(MOUSECOORDS)) { if (e->delta > 0) pWindow->setGroupCurrent(pWindow->m_sGroupData.pNextWindow); @@ -1638,7 +1638,7 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) { if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) continue; - if (wd->getWindowDecorationRegion().containsPoint(mouseCoords)) { + if (g_pDecorationPositioner->getWindowDecorationBox(wd.get()).containsPoint(mouseCoords)) { onDeco = true; break; } diff --git a/src/plugins/PluginAPI.cpp b/src/plugins/PluginAPI.cpp index 1395728d..283472fa 100644 --- a/src/plugins/PluginAPI.cpp +++ b/src/plugins/PluginAPI.cpp @@ -111,7 +111,7 @@ APICALL bool HyprlandAPI::removeFunctionHook(HANDLE handle, CFunctionHook* hook) return g_pFunctionHookSystem->removeHook(hook); } -APICALL bool HyprlandAPI::addWindowDecoration(HANDLE handle, CWindow* pWindow, IHyprWindowDecoration* pDecoration) { +APICALL bool HyprlandAPI::addWindowDecoration(HANDLE handle, CWindow* pWindow, std::unique_ptr pDecoration) { auto* const PLUGIN = g_pPluginSystem->getPluginByHandle(handle); if (!PLUGIN) @@ -120,11 +120,10 @@ APICALL bool HyprlandAPI::addWindowDecoration(HANDLE handle, CWindow* pWindow, I if (!g_pCompositor->windowValidMapped(pWindow)) return false; - PLUGIN->registeredDecorations.push_back(pDecoration); + PLUGIN->registeredDecorations.push_back(pDecoration.get()); - pWindow->m_dWindowDecorations.emplace_back(pDecoration); + pWindow->addWindowDeco(std::move(pDecoration)); - pWindow->updateWindowDecos(); g_pLayoutManager->getCurrentLayout()->recalculateWindow(pWindow); return true; @@ -139,7 +138,7 @@ APICALL bool HyprlandAPI::removeWindowDecoration(HANDLE handle, IHyprWindowDecor for (auto& w : g_pCompositor->m_vWindows) { for (auto& d : w->m_dWindowDecorations) { if (d.get() == pDecoration) { - std::erase(w->m_dWindowDecorations, d); + w->removeWindowDeco(pDecoration); return true; } } diff --git a/src/plugins/PluginAPI.hpp b/src/plugins/PluginAPI.hpp index a3792fe9..12e7c128 100644 --- a/src/plugins/PluginAPI.hpp +++ b/src/plugins/PluginAPI.hpp @@ -221,7 +221,7 @@ namespace HyprlandAPI { returns: true on success. False otherwise. */ - APICALL bool addWindowDecoration(HANDLE handle, CWindow* pWindow, IHyprWindowDecoration* pDecoration); + APICALL bool addWindowDecoration(HANDLE handle, CWindow* pWindow, std::unique_ptr pDecoration); /* Removes a window decoration diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 26f3c128..826854ed 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -497,7 +497,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round return; CRegion damage{m_RenderData.damage}; - damage.intersect(box); + damage.intersect(*box); CFramebuffer* POUTFB = blurMainFramebufferWithDamage(blurA, &damage); @@ -1392,7 +1392,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in if (borderSize < 1) return; - int scaledBorderSize = borderSize * m_RenderData.pMonitor->scale * m_RenderData.renderModif.scale; + int scaledBorderSize = std::round(borderSize * m_RenderData.pMonitor->scale * m_RenderData.renderModif.scale); // adjust box box->x -= scaledBorderSize; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index a43d6a2d..98dcf7f5 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2105,7 +2105,7 @@ void CHyprRenderer::setOccludedForBackLayers(CRegion& region, CWorkspace* pWorks box.scale(PMONITOR->scale); - rg.add(&box); + rg.add(box); } region.subtract(rg); diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index ac6c5b43..9f051ad3 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -10,19 +10,18 @@ CHyprDropShadowDecoration::~CHyprDropShadowDecoration() { updateWindow(m_pWindow); } -SWindowDecorationExtents CHyprDropShadowDecoration::getWindowDecorationExtents() { - static auto* const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue; - - if (*PSHADOWS != 1) - return {{}, {}}; - - return m_seExtents; -} - eDecorationType CHyprDropShadowDecoration::getDecorationType() { return DECORATION_SHADOW; } +SDecorationPositioningInfo CHyprDropShadowDecoration::getPositioningInfo() { + return {DECORATION_POSITION_ABSOLUTE}; +} + +void CHyprDropShadowDecoration::onPositioningReply(const SDecorationPositioningReply& reply) { + updateWindow(m_pWindow); +} + void CHyprDropShadowDecoration::damageEntire() { static auto* const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue; @@ -40,37 +39,11 @@ void CHyprDropShadowDecoration::updateWindow(CWindow* pWindow) { const auto WORKSPACEOFFSET = PWORKSPACE && !pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D(); - if (pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) { - m_vLastWindowPos = pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET; - m_vLastWindowSize = pWindow->m_vRealSize.vec(); + m_vLastWindowPos = pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET; + m_vLastWindowSize = pWindow->m_vRealSize.vec(); - damageEntire(); - - const auto BORDER = m_pWindow->getRealBorderSize(); - - // calculate extents of decos with the DECORATION_PART_OF_MAIN_WINDOW flag - SWindowDecorationExtents maxExtents; - - for (auto& wd : m_pWindow->m_dWindowDecorations) { - // conveniently, this will also skip us. - if (!(wd->getDecorationFlags() & DECORATION_PART_OF_MAIN_WINDOW)) - continue; - - const auto EXTENTS = wd->getWindowDecorationExtents(); - - if (maxExtents.topLeft.x < EXTENTS.topLeft.x) - maxExtents.topLeft.x = EXTENTS.topLeft.x; - if (maxExtents.topLeft.y < EXTENTS.topLeft.y) - maxExtents.topLeft.y = EXTENTS.topLeft.y; - if (maxExtents.bottomRight.x < EXTENTS.bottomRight.x) - maxExtents.bottomRight.x = EXTENTS.bottomRight.x; - if (maxExtents.bottomRight.y < EXTENTS.bottomRight.y) - maxExtents.bottomRight.y = EXTENTS.bottomRight.y; - } - - m_bLastWindowBox = {m_vLastWindowPos.x, m_vLastWindowPos.y, m_vLastWindowSize.x, m_vLastWindowSize.y}; - m_eLastExtents = {{maxExtents.topLeft + Vector2D{BORDER, BORDER}}, {maxExtents.bottomRight + Vector2D{BORDER, BORDER}}}; - } + m_bLastWindowBox = {m_vLastWindowPos.x, m_vLastWindowPos.y, m_vLastWindowSize.x, m_vLastWindowSize.y}; + m_bLastWindowBoxWithDecos = g_pDecorationPositioner->getBoxWithIncludedDecos(pWindow); } void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& offset) { @@ -102,8 +75,8 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D const auto ROUNDING = m_pWindow->rounding() + m_pWindow->getRealBorderSize(); // draw the shadow - CBox fullBox = {m_bLastWindowBox.x, m_bLastWindowBox.y, m_bLastWindowBox.width, m_bLastWindowBox.height}; - fullBox.addExtents(m_eLastExtents).translate(-pMonitor->vecPosition); + CBox fullBox = m_bLastWindowBoxWithDecos; + fullBox.translate(-pMonitor->vecPosition); fullBox.x -= *PSHADOWSIZE; fullBox.y -= *PSHADOWSIZE; fullBox.w += 2 * *PSHADOWSIZE; @@ -134,11 +107,16 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D if (*PSHADOWIGNOREWINDOW) { CBox windowBox = m_bLastWindowBox; + CBox withDecos = m_bLastWindowBoxWithDecos; - windowBox.translate(-pMonitor->vecPosition).scale(pMonitor->scale); - windowBox.round(); + // get window box + windowBox.translate(-pMonitor->vecPosition).scale(pMonitor->scale).round(); + withDecos.translate(-pMonitor->vecPosition).scale(pMonitor->scale).round(); - windowBox.addExtents(SWindowDecorationExtents{m_eLastExtents * pMonitor->scale}.floor()).round(); + auto scaledDecoExtents = withDecos.extentsFrom(windowBox).round(); + + // add extents + windowBox.addExtents(scaledDecoExtents).round(); if (windowBox.width < 1 || windowBox.height < 1) return; // prevent assert failed diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index d7ec043e..9f0f58a0 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -7,17 +7,19 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { CHyprDropShadowDecoration(CWindow*); virtual ~CHyprDropShadowDecoration(); - virtual SWindowDecorationExtents getWindowDecorationExtents(); + virtual SDecorationPositioningInfo getPositioningInfo(); - virtual void draw(CMonitor*, float a, const Vector2D& offset); + virtual void onPositioningReply(const SDecorationPositioningReply& reply); - virtual eDecorationType getDecorationType(); + virtual void draw(CMonitor*, float a, const Vector2D& offset); - virtual void updateWindow(CWindow*); + virtual eDecorationType getDecorationType(); - virtual void damageEntire(); + virtual void updateWindow(CWindow*); - virtual eDecorationLayer getDecorationLayer(); + virtual void damageEntire(); + + virtual eDecorationLayer getDecorationLayer(); private: SWindowDecorationExtents m_seExtents; @@ -27,6 +29,6 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { Vector2D m_vLastWindowPos; Vector2D m_vLastWindowSize; - CBox m_bLastWindowBox = {0}; - SWindowDecorationExtents m_eLastExtents = {}; + CBox m_bLastWindowBox = {0}; + CBox m_bLastWindowBoxWithDecos = {0}; }; \ No newline at end of file diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 873186c0..625888da 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -6,6 +6,10 @@ // shared things to conserve VRAM static CTexture m_tGradientActive; static CTexture m_tGradientInactive; +constexpr int BAR_INDICATOR_HEIGHT = 3; +constexpr int BAR_PADDING_OUTER_VERT = 2; +constexpr int BAR_TEXT_PAD = 2; +constexpr int BAR_HORIZONTAL_PADDING = 2; CHyprGroupBarDecoration::CHyprGroupBarDecoration(CWindow* pWindow) : IHyprWindowDecoration(pWindow) { m_pWindow = pWindow; @@ -13,47 +17,33 @@ CHyprGroupBarDecoration::CHyprGroupBarDecoration(CWindow* pWindow) : IHyprWindow CHyprGroupBarDecoration::~CHyprGroupBarDecoration() {} -SWindowDecorationExtents CHyprGroupBarDecoration::getWindowDecorationExtents() { - return m_seExtents; +SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() { + const int BORDERSIZE = m_pWindow->getRealBorderSize(); + static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("group:groupbar:render_titles")->intValue; + static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue; + + SDecorationPositioningInfo info; + info.policy = DECORATION_POSITION_STICKY; + info.edges = DECORATION_EDGE_TOP; + info.priority = 3; + info.reserved = true; + info.desiredExtents = {{0, BORDERSIZE + BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0) + 2}, {0, 0}}; + return info; +} + +void CHyprGroupBarDecoration::onPositioningReply(const SDecorationPositioningReply& reply) { + m_bAssignedBox = reply.assignedGeometry; } eDecorationType CHyprGroupBarDecoration::getDecorationType() { return DECORATION_GROUPBAR; } -constexpr int BAR_INDICATOR_HEIGHT = 3; -constexpr int BAR_PADDING_OUTER_VERT = 2; -constexpr int BAR_TEXT_PAD = 2; -constexpr int BAR_HORIZONTAL_PADDING = 2; - // void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) { - damageEntire(); - - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); - - const auto WORKSPACEOFFSET = PWORKSPACE && !pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D(); - - static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("group:groupbar:render_titles")->intValue; - static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue; - - if (pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET != m_vLastWindowPos || pWindow->m_vRealSize.vec() != m_vLastWindowSize) { - // we draw 3px above the window's border with 3px - - const int BORDERSIZE = pWindow->getRealBorderSize(); - - m_seExtents.topLeft = Vector2D(0, BORDERSIZE + BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0) + 2); - m_seExtents.bottomRight = Vector2D(); - - m_vLastWindowPos = pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET; - m_vLastWindowSize = pWindow->m_vRealSize.vec(); - - invalidateTextures(); - } - if (!m_pWindow->m_sGroupData.pNextWindow) { - m_pWindow->m_vDecosToRemove.push_back(this); + m_pWindow->removeWindowDeco(this); return; } @@ -70,15 +60,14 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) { damageEntire(); if (m_dwGroupMembers.size() == 0) { - m_pWindow->m_vDecosToRemove.push_back(this); + m_pWindow->removeWindowDeco(this); return; } } void CHyprGroupBarDecoration::damageEntire() { - CBox dm = {m_vLastWindowPos.x - m_seExtents.topLeft.x, m_vLastWindowPos.y - m_seExtents.topLeft.y, m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x, - m_seExtents.topLeft.y}; - g_pHyprRenderer->damageBox(&dm); + auto box = assignedBoxGlobal(); + g_pHyprRenderer->damageBox(&box); } void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& offset) { @@ -94,13 +83,19 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& if (!m_pWindow->m_sSpecialRenderData.decorate) return; - m_fBarWidth = (m_vLastWindowSize.x - BAR_HORIZONTAL_PADDING * (barsToDraw - 1)) / barsToDraw; + const auto ASSIGNEDBOX = assignedBoxGlobal(); + + m_fBarWidth = (ASSIGNEDBOX.w - BAR_HORIZONTAL_PADDING * (barsToDraw - 1)) / barsToDraw; + + const auto DESIREDHEIGHT = BORDERSIZE + BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0) + 2; + if (DESIREDHEIGHT != ASSIGNEDBOX.h) + g_pDecorationPositioner->repositionDeco(this); int xoff = 0; for (int i = 0; i < barsToDraw; ++i) { - CBox rect = {m_vLastWindowPos.x + xoff - pMonitor->vecPosition.x + offset.x, - m_vLastWindowPos.y - BAR_PADDING_OUTER_VERT - BORDERSIZE - BAR_INDICATOR_HEIGHT - pMonitor->vecPosition.y + offset.y, m_fBarWidth, BAR_INDICATOR_HEIGHT}; + CBox rect = {ASSIGNEDBOX.x + xoff - pMonitor->vecPosition.x + offset.x, + ASSIGNEDBOX.y + ASSIGNEDBOX.h - BAR_INDICATOR_HEIGHT - BAR_PADDING_OUTER_VERT - pMonitor->vecPosition.y + offset.y, m_fBarWidth, BAR_INDICATOR_HEIGHT}; if (rect.width <= 0 || rect.height <= 0) break; @@ -123,6 +118,9 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& // render title if necessary if (*PRENDERTITLES) { + CBox rect = {ASSIGNEDBOX.x + xoff - pMonitor->vecPosition.x + offset.x, ASSIGNEDBOX.y - pMonitor->vecPosition.y + offset.y + BAR_PADDING_OUTER_VERT, m_fBarWidth, + ASSIGNEDBOX.h - BAR_INDICATOR_HEIGHT - BAR_PADDING_OUTER_VERT * 2}; + CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[i]->m_szTitle); if (!pTitleTex) @@ -131,17 +129,15 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale})) .get(); - rect.height = (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * 0.8 * pMonitor->scale; - - rect.y -= rect.height; - rect.width = m_fBarWidth * pMonitor->scale; - refreshGradients(); - if (*PGRADIENTS) - g_pHyprOpenGL->renderTexture((m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? m_tGradientActive : m_tGradientInactive), &rect, 1.0); + if (*PGRADIENTS) { + CBox rect2 = rect; + rect2.scale(pMonitor->scale); + g_pHyprOpenGL->renderTexture((m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? m_tGradientActive : m_tGradientInactive), &rect2, 1.0); + } - rect.y -= (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * 0.2 * pMonitor->scale; + rect.y = ASSIGNEDBOX.y + ASSIGNEDBOX.h / 2.0 - (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) / 2.0; rect.height = (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale; g_pHyprOpenGL->renderTexture(pTitleTex->tex, &rect, 1.f); @@ -154,12 +150,6 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& invalidateTextures(); } -SWindowDecorationExtents CHyprGroupBarDecoration::getWindowDecorationReservedArea() { - static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("group:groupbar:render_titles")->intValue; - static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue; - return SWindowDecorationExtents{{0, BAR_INDICATOR_HEIGHT + BAR_PADDING_OUTER_VERT * 2 + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0)}, {}}; -} - CTitleTex* CHyprGroupBarDecoration::textureFromTitle(const std::string& title) { for (auto& tex : m_sTitleTexs.titleTexs) { if (tex->szContent == title) @@ -307,7 +297,7 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(CWindow* pDraggedWindow, con if (!pDraggedWindow->canBeGroupedInto(m_pWindow)) return true; - const float BARRELATIVEX = pos.x - m_vLastWindowPos.x - m_fBarWidth / 2; + const float BARRELATIVEX = pos.x - assignedBoxGlobal().x - m_fBarWidth / 2; const int WINDOWINDEX = BARRELATIVEX < 0 ? -1 : (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); CWindow* pWindowInsertAfter = m_pWindow->getGroupWindowByIndex(WINDOWINDEX); @@ -363,7 +353,7 @@ void CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, wlr_point if (e->state != WLR_BUTTON_PRESSED) return; - const float BARRELATIVEX = pos.x - m_vLastWindowPos.x; + const float BARRELATIVEX = pos.x - assignedBoxGlobal().x; const int WINDOWINDEX = (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); if (BARRELATIVEX - (m_fBarWidth + BAR_HORIZONTAL_PADDING) * WINDOWINDEX > m_fBarWidth) { @@ -382,7 +372,7 @@ void CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, wlr_point } void CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) { - const float BARRELATIVEX = pos.x - m_vLastWindowPos.x; + const float BARRELATIVEX = pos.x - assignedBoxGlobal().x; const int WINDOWINDEX = (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); if (BARRELATIVEX - (m_fBarWidth + BAR_HORIZONTAL_PADDING) * WINDOWINDEX > m_fBarWidth) @@ -411,4 +401,9 @@ eDecorationLayer CHyprGroupBarDecoration::getDecorationLayer() { uint64_t CHyprGroupBarDecoration::getDecorationFlags() { return DECORATION_ALLOWS_MOUSE_INPUT; +} + +CBox CHyprGroupBarDecoration::assignedBoxGlobal() { + CBox box = m_bAssignedBox; + return box.translate(g_pDecorationPositioner->getEdgeDefinedPoint(DECORATION_EDGE_TOP, m_pWindow)); } \ No newline at end of file diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp index 569fda21..52439942 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.hpp +++ b/src/render/decorations/CHyprGroupBarDecoration.hpp @@ -21,35 +21,34 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { CHyprGroupBarDecoration(CWindow*); virtual ~CHyprGroupBarDecoration(); - virtual SWindowDecorationExtents getWindowDecorationExtents(); + virtual SDecorationPositioningInfo getPositioningInfo(); - virtual void draw(CMonitor*, float a, const Vector2D& offset); + virtual void onPositioningReply(const SDecorationPositioningReply& reply); - virtual eDecorationType getDecorationType(); + virtual void draw(CMonitor*, float a, const Vector2D& offset); - virtual void updateWindow(CWindow*); + virtual eDecorationType getDecorationType(); - virtual void damageEntire(); + virtual void updateWindow(CWindow*); - virtual SWindowDecorationExtents getWindowDecorationReservedArea(); + virtual void damageEntire(); - virtual void onBeginWindowDragOnDeco(const Vector2D&); + virtual void onBeginWindowDragOnDeco(const Vector2D&); - virtual bool onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D&); + virtual bool onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D&); - virtual void onMouseButtonOnDeco(const Vector2D&, wlr_pointer_button_event*); + virtual void onMouseButtonOnDeco(const Vector2D&, wlr_pointer_button_event*); - virtual eDecorationLayer getDecorationLayer(); + virtual eDecorationLayer getDecorationLayer(); - virtual uint64_t getDecorationFlags(); + virtual uint64_t getDecorationFlags(); private: SWindowDecorationExtents m_seExtents; - CWindow* m_pWindow = nullptr; + CBox m_bAssignedBox = {0}; - Vector2D m_vLastWindowPos; - Vector2D m_vLastWindowSize; + CWindow* m_pWindow = nullptr; std::deque m_dwGroupMembers; @@ -60,6 +59,8 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { void refreshGradients(); + CBox assignedBoxGlobal(); + struct STitleTexs { // STitleTexs* overriden = nullptr; // TODO: make shit shared in-group to decrease VRAM usage. std::deque> titleTexs; diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp new file mode 100644 index 00000000..5a8a4275 --- /dev/null +++ b/src/render/decorations/DecorationPositioner.cpp @@ -0,0 +1,277 @@ +#include "DecorationPositioner.hpp" +#include "../../Compositor.hpp" + +CDecorationPositioner::CDecorationPositioner() { + g_pHookSystem->hookDynamic("closeWindow", [this](void* call, SCallbackInfo& info, std::any data) { + auto* const PWINDOW = std::any_cast(data); + this->onWindowUnmap(PWINDOW); + }); +} + +Vector2D CDecorationPositioner::getEdgeDefinedPoint(uint32_t edges, CWindow* pWindow) { + const bool TOP = edges & DECORATION_EDGE_TOP; + const bool BOTTOM = edges & DECORATION_EDGE_BOTTOM; + const bool LEFT = edges & DECORATION_EDGE_LEFT; + const bool RIGHT = edges & DECORATION_EDGE_RIGHT; + + const int EDGESNO = TOP + BOTTOM + LEFT + RIGHT; + + if (EDGESNO == 0 || EDGESNO > 2) { + Debug::log(ERR, "getEdgeDefinedPoint: invalid number of edges"); + return {}; + } + + CBox wb = pWindow->getWindowMainSurfaceBox(); + const auto BORDERSIZE = pWindow->getRealBorderSize(); + wb.expand(BORDERSIZE); + + if (EDGESNO == 1) { + if (TOP) + return wb.pos() + Vector2D{wb.size().x / 2.0, 0}; + else if (BOTTOM) + return wb.pos() + Vector2D{wb.size().x / 2.0, wb.size().y}; + else if (LEFT) + return wb.pos() + Vector2D{0, wb.size().y / 2.0}; + else if (RIGHT) + return wb.pos() + Vector2D{wb.size().x, wb.size().y / 2.0}; + UNREACHABLE(); + } else { + if (TOP && LEFT) + return wb.pos(); + if (TOP && RIGHT) + return wb.pos() + Vector2D{wb.size().x, 0}; + if (BOTTOM && RIGHT) + return wb.pos() + wb.size(); + if (BOTTOM && LEFT) + return wb.pos() + Vector2D{0, wb.size().y}; + UNREACHABLE(); + } + UNREACHABLE(); + return {}; +} + +void CDecorationPositioner::uncacheDecoration(IHyprWindowDecoration* deco) { + std::erase_if(m_vWindowPositioningDatas, [&](const auto& data) { return data->pDecoration == deco; }); +} + +void CDecorationPositioner::repositionDeco(IHyprWindowDecoration* deco) { + uncacheDecoration(deco); + onWindowUpdate(deco->m_pWindow); +} + +CDecorationPositioner::SWindowPositioningData* CDecorationPositioner::getDataFor(IHyprWindowDecoration* pDecoration, CWindow* pWindow) { + auto it = std::find_if(m_vWindowPositioningDatas.begin(), m_vWindowPositioningDatas.end(), [&](const auto& el) { return el->pDecoration == pDecoration; }); + + if (it != m_vWindowPositioningDatas.end()) + return it->get(); + + const auto DATA = m_vWindowPositioningDatas.emplace_back(std::make_unique(pWindow, pDecoration)).get(); + + DATA->positioningInfo = pDecoration->getPositioningInfo(); + + return DATA; +} + +void CDecorationPositioner::onWindowUpdate(CWindow* pWindow) { + if (!g_pCompositor->windowValidMapped(pWindow)) + return; + + auto* const WINDOWDATA = &m_mWindowDatas[pWindow]; + + // + std::vector datas; + for (auto& wd : pWindow->m_dWindowDecorations) { + datas.push_back(getDataFor(wd.get(), pWindow)); + } + + if (WINDOWDATA->lastWindowSize == pWindow->m_vRealSize.vec() /* position not changed */ + && + std::all_of(m_vWindowPositioningDatas.begin(), m_vWindowPositioningDatas.end(), [pWindow](const auto& data) { return pWindow != data->pWindow || !data->needsReposition; }) + /* all window datas are either not for this window or don't need a reposition */ + ) + return; + + WINDOWDATA->lastWindowSize = pWindow->m_vRealSize.vec(); + const bool EPHEMERAL = pWindow->m_vRealSize.isBeingAnimated(); + + std::sort(datas.begin(), datas.end(), [](const auto& a, const auto& b) { return a->positioningInfo.priority > b->positioningInfo.priority; }); + + CBox wb = pWindow->getWindowMainSurfaceBox(); + const auto BORDERSIZE = pWindow->getRealBorderSize(); + wb.expand(BORDERSIZE); + + // calc reserved + float reservedXL = 0, reservedYT = 0, reservedXR = 0, reservedYB = 0; + for (size_t i = 0; i < datas.size(); ++i) { + auto* const wd = datas[i]; + + if (!wd->positioningInfo.reserved) + continue; + + const bool TOP = wd->positioningInfo.edges & DECORATION_EDGE_TOP; + const bool BOTTOM = wd->positioningInfo.edges & DECORATION_EDGE_BOTTOM; + const bool LEFT = wd->positioningInfo.edges & DECORATION_EDGE_LEFT; + const bool RIGHT = wd->positioningInfo.edges & DECORATION_EDGE_RIGHT; + + if (LEFT) + reservedXL += wd->positioningInfo.desiredExtents.topLeft.x; + if (RIGHT) + reservedXR += wd->positioningInfo.desiredExtents.bottomRight.x; + if (TOP) + reservedYT += wd->positioningInfo.desiredExtents.topLeft.y; + if (BOTTOM) + reservedYB += wd->positioningInfo.desiredExtents.bottomRight.y; + } + + WINDOWDATA->reserved = {{reservedXL, reservedYT}, {reservedXR, reservedYB}}; + + float stickyOffsetXL = 0, stickyOffsetYT = 0, stickyOffsetXR = 0, stickyOffsetYB = 0; + + for (size_t i = 0; i < datas.size(); ++i) { + auto* const wd = datas[i]; + + wd->needsReposition = false; + + const bool TOP = wd->positioningInfo.edges & DECORATION_EDGE_TOP; + const bool BOTTOM = wd->positioningInfo.edges & DECORATION_EDGE_BOTTOM; + const bool LEFT = wd->positioningInfo.edges & DECORATION_EDGE_LEFT; + const bool RIGHT = wd->positioningInfo.edges & DECORATION_EDGE_RIGHT; + const int EDGESNO = TOP + BOTTOM + LEFT + RIGHT; + + if (wd->positioningInfo.policy == DECORATION_POSITION_ABSOLUTE) { + if (LEFT) + stickyOffsetXL += wd->positioningInfo.desiredExtents.topLeft.x; + if (RIGHT) + stickyOffsetXR += wd->positioningInfo.desiredExtents.bottomRight.x; + if (TOP) + stickyOffsetYT += wd->positioningInfo.desiredExtents.topLeft.y; + if (BOTTOM) + stickyOffsetYB += wd->positioningInfo.desiredExtents.bottomRight.y; + + wd->lastReply = {}; + wd->pDecoration->onPositioningReply({}); + continue; + } + + if (wd->positioningInfo.policy == DECORATION_POSITION_STICKY) { + if (EDGESNO != 1) { + wd->lastReply = {}; + wd->pDecoration->onPositioningReply({}); + continue; + } + + auto desiredSize = 0; + if (LEFT) + desiredSize = wd->positioningInfo.desiredExtents.topLeft.x; + else if (RIGHT) + desiredSize = wd->positioningInfo.desiredExtents.bottomRight.x; + else if (TOP) + desiredSize = wd->positioningInfo.desiredExtents.topLeft.y; + else + desiredSize = wd->positioningInfo.desiredExtents.bottomRight.y; + + const auto EDGEPOINT = getEdgeDefinedPoint(wd->positioningInfo.edges, pWindow); + + Vector2D pos, size; + + if (LEFT) { + pos = wb.pos() - EDGEPOINT - Vector2D{stickyOffsetXL, 0}; + pos.x -= desiredSize; + size = {desiredSize, wb.size().y}; + + stickyOffsetXL += desiredSize; + } else if (RIGHT) { + pos = wb.pos() + Vector2D{wb.size().x, 0} - EDGEPOINT + Vector2D{stickyOffsetXR, 0}; + size = {desiredSize, wb.size().y}; + + stickyOffsetXR += desiredSize; + } else if (TOP) { + pos = wb.pos() - EDGEPOINT - Vector2D{0, stickyOffsetYT}; + pos.y -= desiredSize; + size = {wb.size().x, desiredSize}; + + stickyOffsetYT += desiredSize; + } else { + pos = wb.pos() + Vector2D{0, wb.size().y} - EDGEPOINT - Vector2D{0, stickyOffsetYB}; + size = {wb.size().x, desiredSize}; + + stickyOffsetYB += desiredSize; + } + + wd->lastReply = {{pos, size}, EPHEMERAL}; + wd->pDecoration->onPositioningReply(wd->lastReply); + + continue; + } else { + // invalid + wd->lastReply = {}; + wd->pDecoration->onPositioningReply({}); + continue; + } + } + + WINDOWDATA->extents = {{stickyOffsetXL + reservedXL, stickyOffsetYT + reservedYT}, {stickyOffsetXR + reservedXR, stickyOffsetYB + reservedYB}}; +} + +void CDecorationPositioner::onWindowUnmap(CWindow* pWindow) { + std::erase_if(m_vWindowPositioningDatas, [&](const auto& data) { return data->pWindow == pWindow; }); + m_mWindowDatas.erase(pWindow); +} + +SWindowDecorationExtents CDecorationPositioner::getWindowDecorationReserved(CWindow* pWindow) { + return m_mWindowDatas[pWindow].reserved; +} + +SWindowDecorationExtents CDecorationPositioner::getWindowDecorationExtents(CWindow* pWindow, bool inputOnly) { + if (!inputOnly) + return m_mWindowDatas[pWindow].extents; + + // TODO: + return m_mWindowDatas[pWindow].extents; +} + +CBox CDecorationPositioner::getBoxWithIncludedDecos(CWindow* pWindow) { + CBox accum = pWindow->getWindowMainSurfaceBox().expand(pWindow->getRealBorderSize()); + + for (auto& data : m_vWindowPositioningDatas) { + if (data->pWindow != pWindow) + continue; + + if (!(data->pDecoration->getDecorationFlags() & DECORATION_PART_OF_MAIN_WINDOW)) + continue; + + CBox decoBox; + + if (data->positioningInfo.policy == DECORATION_POSITION_ABSOLUTE) { + decoBox = data->pWindow->getWindowMainSurfaceBox(); + decoBox.addExtents(data->positioningInfo.desiredExtents); + } else { + decoBox = data->lastReply.assignedGeometry; + const auto EDGEPOINT = getEdgeDefinedPoint(data->positioningInfo.edges, pWindow); + decoBox.translate(EDGEPOINT); + } + + SWindowDecorationExtents extentsToAdd; + + if (decoBox.x < accum.x) + extentsToAdd.topLeft.x = accum.x - decoBox.x; + if (decoBox.y < accum.y) + extentsToAdd.topLeft.y = accum.y - decoBox.y; + if (decoBox.x + decoBox.w > accum.x + accum.w) + extentsToAdd.bottomRight.x = accum.x + accum.w - (decoBox.x + decoBox.w); + if (decoBox.y + decoBox.h > accum.y + accum.h) + extentsToAdd.bottomRight.y = accum.y + accum.h - (decoBox.y + decoBox.h); + + accum.addExtents(extentsToAdd); + } + + return accum; +} + +CBox CDecorationPositioner::getWindowDecorationBox(IHyprWindowDecoration* deco) { + const auto DATA = getDataFor(deco, deco->m_pWindow); + + CBox box = DATA->lastReply.assignedGeometry; + box.translate(getEdgeDefinedPoint(DATA->positioningInfo.edges, deco->m_pWindow)); + return box; +} \ No newline at end of file diff --git a/src/render/decorations/DecorationPositioner.hpp b/src/render/decorations/DecorationPositioner.hpp new file mode 100644 index 00000000..c85bc217 --- /dev/null +++ b/src/render/decorations/DecorationPositioner.hpp @@ -0,0 +1,96 @@ +#pragma once + +#include +#include +#include +#include +#include "../../helpers/Box.hpp" + +class CWindow; +class IHyprWindowDecoration; + +enum eDecorationPositioningPolicy +{ + DECORATION_POSITION_ABSOLUTE = 0, /* Decoration does not interfere with anything else */ + DECORATION_POSITION_STICKY, /* Decoration is stuck to some edge of a window */ +}; + +enum eDecorationEdges +{ + DECORATION_EDGE_TOP = 1 << 0, + DECORATION_EDGE_BOTTOM = 1 << 1, + DECORATION_EDGE_LEFT = 1 << 2, + DECORATION_EDGE_RIGHT = 1 << 3 +}; + +/* +Request the positioner to position a decoration + +DECORATION_POSITION_ABSOLUTE: + - desiredExtents may contain the extents to be used when reserved is set. Edges has to have the edges used. +DECORATION_POSITION_STICKY: + - one edge allowed + - priority allowed + - desiredExtents contains the desired extents. Any other edge than the one selected is ignored. + - reserved is allowed +*/ +struct SDecorationPositioningInfo { + eDecorationPositioningPolicy policy = DECORATION_POSITION_ABSOLUTE; + uint32_t edges = 0; // enum eDecorationEdges + uint32_t priority = 10; // priority, decos will be evaluated high -> low + SWindowDecorationExtents desiredExtents; + bool reserved = false; // if true, geometry will use reserved area +}; + +/* +A reply from the positioner. This may be sent multiple times, if anything changes. + +DECORATION_POSITION_ABSOLUTE: + - assignedGeometry is empty +DECORATION_POSITION_STICKY: + - assignedGeometry is relative to the edge's center point + - ephemeral is sent +*/ +struct SDecorationPositioningReply { + CBox assignedGeometry; + bool ephemeral = false; // if true, means it's a result of an animation and will change soon. +}; + +class CDecorationPositioner { + public: + CDecorationPositioner(); + + Vector2D getEdgeDefinedPoint(uint32_t edges, CWindow* pWindow); + + // called on resize, or insert/removal of a new deco + void onWindowUpdate(CWindow* pWindow); + void uncacheDecoration(IHyprWindowDecoration* deco); + SWindowDecorationExtents getWindowDecorationReserved(CWindow* pWindow); + SWindowDecorationExtents getWindowDecorationExtents(CWindow* pWindow, bool inputOnly = false); + CBox getBoxWithIncludedDecos(CWindow* pWindow); + void repositionDeco(IHyprWindowDecoration* deco); + CBox getWindowDecorationBox(IHyprWindowDecoration* deco); + + private: + struct SWindowPositioningData { + CWindow* pWindow = nullptr; + IHyprWindowDecoration* pDecoration = nullptr; + SDecorationPositioningInfo positioningInfo; + SDecorationPositioningReply lastReply; + bool needsReposition = true; + }; + + struct SWindowData { + Vector2D lastWindowSize = {}; + SWindowDecorationExtents reserved = {}; + SWindowDecorationExtents extents = {}; + }; + + std::unordered_map m_mWindowDatas; + std::vector> m_vWindowPositioningDatas; + + SWindowPositioningData* getDataFor(IHyprWindowDecoration* pDecoration, CWindow* pWindow); + void onWindowUnmap(CWindow* pWindow); +}; + +inline std::unique_ptr g_pDecorationPositioner; \ No newline at end of file diff --git a/src/render/decorations/IHyprWindowDecoration.cpp b/src/render/decorations/IHyprWindowDecoration.cpp index d2b9b0f9..7a4906b5 100644 --- a/src/render/decorations/IHyprWindowDecoration.cpp +++ b/src/render/decorations/IHyprWindowDecoration.cpp @@ -8,23 +8,6 @@ IHyprWindowDecoration::IHyprWindowDecoration(CWindow* pWindow) { IHyprWindowDecoration::~IHyprWindowDecoration() {} -SWindowDecorationExtents IHyprWindowDecoration::getWindowDecorationReservedArea() { - return SWindowDecorationExtents{}; -} - -CRegion IHyprWindowDecoration::getWindowDecorationRegion() { - const SWindowDecorationExtents RESERVED = getWindowDecorationReservedArea(); - const int BORDERSIZE = m_pWindow->getRealBorderSize(); - return CRegion(m_pWindow->m_vRealPosition.vec().x - (BORDERSIZE + RESERVED.topLeft.x) * (int)(RESERVED.topLeft.x != 0), - m_pWindow->m_vRealPosition.vec().y - (BORDERSIZE + RESERVED.topLeft.y) * (int)(RESERVED.topLeft.y != 0), - m_pWindow->m_vRealSize.vec().x + (BORDERSIZE + RESERVED.topLeft.x) * (int)(RESERVED.topLeft.x != 0) + - (BORDERSIZE + RESERVED.bottomRight.x) * (int)(RESERVED.bottomRight.x != 0), - m_pWindow->m_vRealSize.vec().y + (BORDERSIZE + RESERVED.topLeft.y) * (int)(RESERVED.topLeft.y != 0) + - (BORDERSIZE + RESERVED.bottomRight.y) * (int)(RESERVED.bottomRight.y != 0)) - .subtract(CRegion(m_pWindow->m_vRealPosition.vec().x - BORDERSIZE, m_pWindow->m_vRealPosition.vec().y - BORDERSIZE, m_pWindow->m_vRealSize.vec().x + 2 * BORDERSIZE, - m_pWindow->m_vRealSize.vec().y + 2 * BORDERSIZE)); -} - void IHyprWindowDecoration::onBeginWindowDragOnDeco(const Vector2D&) { ; } diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp index 47945b38..15890f44 100644 --- a/src/render/decorations/IHyprWindowDecoration.hpp +++ b/src/render/decorations/IHyprWindowDecoration.hpp @@ -2,6 +2,7 @@ #include "../../defines.hpp" #include "../../helpers/Region.hpp" +#include "DecorationPositioner.hpp" enum eDecorationType { @@ -27,36 +28,37 @@ enum eDecorationFlags class CWindow; class CMonitor; +class CDecorationPositioner; class IHyprWindowDecoration { public: IHyprWindowDecoration(CWindow*); virtual ~IHyprWindowDecoration() = 0; - virtual SWindowDecorationExtents getWindowDecorationExtents() = 0; + virtual SDecorationPositioningInfo getPositioningInfo() = 0; - virtual void draw(CMonitor*, float a, const Vector2D& offset = Vector2D()) = 0; + virtual void onPositioningReply(const SDecorationPositioningReply& reply) = 0; - virtual eDecorationType getDecorationType() = 0; + virtual void draw(CMonitor*, float a, const Vector2D& offset = Vector2D()) = 0; - virtual void updateWindow(CWindow*) = 0; + virtual eDecorationType getDecorationType() = 0; - virtual void damageEntire() = 0; + virtual void updateWindow(CWindow*) = 0; - virtual SWindowDecorationExtents getWindowDecorationReservedArea(); + virtual void damageEntire() = 0; // should be ignored by non-absolute decos - virtual CRegion getWindowDecorationRegion(); + virtual void onBeginWindowDragOnDeco(const Vector2D&); // called when the user calls the "movewindow" mouse dispatcher on the deco - virtual void onBeginWindowDragOnDeco(const Vector2D&); // called when the user calls the "movewindow" mouse dispatcher on the deco + virtual bool onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D&); // returns true if the window should be placed by the layout - virtual bool onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D&); // returns true if the window should be placed by the layout + virtual void onMouseButtonOnDeco(const Vector2D&, wlr_pointer_button_event*); - virtual void onMouseButtonOnDeco(const Vector2D&, wlr_pointer_button_event*); + virtual eDecorationLayer getDecorationLayer(); - virtual eDecorationLayer getDecorationLayer(); - - virtual uint64_t getDecorationFlags(); + virtual uint64_t getDecorationFlags(); private: CWindow* m_pWindow = nullptr; + + friend class CDecorationPositioner; }; From 9b5e2e71e0a334c722cc501c000ab12a80696c10 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 11 Nov 2023 14:47:25 +0000 Subject: [PATCH 206/513] deps: update wlroots --- subprojects/wlroots | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/wlroots b/subprojects/wlroots index 47bf87ad..5de9e1a9 160000 --- a/subprojects/wlroots +++ b/subprojects/wlroots @@ -1 +1 @@ -Subproject commit 47bf87ade2bd32395615a385ebde1fefbcdf79a2 +Subproject commit 5de9e1a99d6642c2d09d589aa37ff0a8945dcee1 From cc04b52ce1f056817df5a1395ebc65fed7b9161f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 11 Nov 2023 14:52:27 +0000 Subject: [PATCH 207/513] deco-positioner: recalc after uncache --- src/render/decorations/DecorationPositioner.cpp | 3 +++ src/render/decorations/DecorationPositioner.hpp | 1 + 2 files changed, 4 insertions(+) diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index 5a8a4275..98627d4c 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -52,6 +52,7 @@ Vector2D CDecorationPositioner::getEdgeDefinedPoint(uint32_t edges, CWindow* pWi void CDecorationPositioner::uncacheDecoration(IHyprWindowDecoration* deco) { std::erase_if(m_vWindowPositioningDatas, [&](const auto& data) { return data->pDecoration == deco; }); + m_mWindowDatas[deco->m_pWindow].needsRecalc = true; } void CDecorationPositioner::repositionDeco(IHyprWindowDecoration* deco) { @@ -88,10 +89,12 @@ void CDecorationPositioner::onWindowUpdate(CWindow* pWindow) { && std::all_of(m_vWindowPositioningDatas.begin(), m_vWindowPositioningDatas.end(), [pWindow](const auto& data) { return pWindow != data->pWindow || !data->needsReposition; }) /* all window datas are either not for this window or don't need a reposition */ + && !WINDOWDATA->needsRecalc /* window doesn't need recalc */ ) return; WINDOWDATA->lastWindowSize = pWindow->m_vRealSize.vec(); + WINDOWDATA->needsRecalc = false; const bool EPHEMERAL = pWindow->m_vRealSize.isBeingAnimated(); std::sort(datas.begin(), datas.end(), [](const auto& a, const auto& b) { return a->positioningInfo.priority > b->positioningInfo.priority; }); diff --git a/src/render/decorations/DecorationPositioner.hpp b/src/render/decorations/DecorationPositioner.hpp index c85bc217..9fc45ba3 100644 --- a/src/render/decorations/DecorationPositioner.hpp +++ b/src/render/decorations/DecorationPositioner.hpp @@ -84,6 +84,7 @@ class CDecorationPositioner { Vector2D lastWindowSize = {}; SWindowDecorationExtents reserved = {}; SWindowDecorationExtents extents = {}; + bool needsRecalc = false; }; std::unordered_map m_mWindowDatas; From c5d1faf72dc5e7e4fa357007974ced0f573f1f32 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 11 Nov 2023 14:53:18 +0000 Subject: [PATCH 208/513] [gha] Nix: update wlroots --- flake.lock | 8 ++++---- flake.nix | 2 +- subprojects/wlroots.wrap | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 8bb0d13d..fcb03328 100644 --- a/flake.lock +++ b/flake.lock @@ -67,18 +67,18 @@ "flake": false, "locked": { "host": "gitlab.freedesktop.org", - "lastModified": 1697909146, - "narHash": "sha256-jU0I6FoCKnj4zIBL4daosFWh81U1fM719Z6cae8PxSY=", + "lastModified": 1699292815, + "narHash": "sha256-HXu98PyBMKEWLqiTb8viuLDznud/SdkdJsx5A5CWx7I=", "owner": "wlroots", "repo": "wlroots", - "rev": "47bf87ade2bd32395615a385ebde1fefbcdf79a2", + "rev": "5de9e1a99d6642c2d09d589aa37ff0a8945dcee1", "type": "gitlab" }, "original": { "host": "gitlab.freedesktop.org", "owner": "wlroots", "repo": "wlroots", - "rev": "47bf87ade2bd32395615a385ebde1fefbcdf79a2", + "rev": "5de9e1a99d6642c2d09d589aa37ff0a8945dcee1", "type": "gitlab" } }, diff --git a/flake.nix b/flake.nix index 78677c20..f2602105 100644 --- a/flake.nix +++ b/flake.nix @@ -12,7 +12,7 @@ host = "gitlab.freedesktop.org"; owner = "wlroots"; repo = "wlroots"; - rev = "47bf87ade2bd32395615a385ebde1fefbcdf79a2"; + rev = "5de9e1a99d6642c2d09d589aa37ff0a8945dcee1"; flake = false; }; diff --git a/subprojects/wlroots.wrap b/subprojects/wlroots.wrap index b3cac63f..7df8166b 100644 --- a/subprojects/wlroots.wrap +++ b/subprojects/wlroots.wrap @@ -1,7 +1,7 @@ [wrap-git] directory = wlroots url = https://gitlab.freedesktop.org/wlroots/wlroots.git -revision = 47bf87ade2bd32395615a385ebde1fefbcdf79a2 +revision = 5de9e1a99d6642c2d09d589aa37ff0a8945dcee1 depth = 1 diff_files = wlroots-meson-build.patch From bea828ea4585bab206b8772b838f496e0eada12e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 11 Nov 2023 15:18:04 +0000 Subject: [PATCH 209/513] decoration-positioner: improve extent handling --- src/SharedDefs.hpp | 4 ++ src/events/Windows.cpp | 14 +++---- .../decorations/CHyprDropShadowDecoration.cpp | 17 ++++++--- .../decorations/CHyprDropShadowDecoration.hpp | 1 + .../decorations/DecorationPositioner.cpp | 38 +++++++++++++++++-- .../decorations/DecorationPositioner.hpp | 3 +- 6 files changed, 60 insertions(+), 17 deletions(-) diff --git a/src/SharedDefs.hpp b/src/SharedDefs.hpp index 4e4217d2..19d26b61 100644 --- a/src/SharedDefs.hpp +++ b/src/SharedDefs.hpp @@ -42,4 +42,8 @@ struct SWindowDecorationExtents { SWindowDecorationExtents round() { return {topLeft.round(), bottomRight.round()}; } + + bool operator==(const SWindowDecorationExtents& other) const { + return topLeft == other.topLeft && bottomRight == other.bottomRight; + } }; \ No newline at end of file diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index c6c9024e..00d78f4c 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -668,6 +668,13 @@ void Events::listener_unmapWindow(void* owner, void* data) { return; } + const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + if (PMONITOR) { + PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec() - PMONITOR->vecPosition; + PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.vec(); + PWINDOW->m_eOriginalClosedExtents = PWINDOW->getFullWindowExtents(); + } + g_pEventManager->postEvent(SHyprIPCEvent{"closewindow", std::format("{:x}", PWINDOW)}); EMIT_HOOK_EVENT("closeWindow", PWINDOW); @@ -697,13 +704,6 @@ void Events::listener_unmapWindow(void* owner, void* data) { if (PWINDOW->m_bIsFullscreen) g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL); - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); - if (PMONITOR) { - PWINDOW->m_vOriginalClosedPos = PWINDOW->m_vRealPosition.vec() - PMONITOR->vecPosition; - PWINDOW->m_vOriginalClosedSize = PWINDOW->m_vRealSize.vec(); - PWINDOW->m_eOriginalClosedExtents = PWINDOW->getFullWindowExtents(); - } - // Allow the renderer to catch the last frame. g_pHyprOpenGL->makeWindowSnapshot(PWINDOW); diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 9f051ad3..1990d37d 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -6,16 +6,20 @@ CHyprDropShadowDecoration::CHyprDropShadowDecoration(CWindow* pWindow) : IHyprWi m_pWindow = pWindow; } -CHyprDropShadowDecoration::~CHyprDropShadowDecoration() { - updateWindow(m_pWindow); -} +CHyprDropShadowDecoration::~CHyprDropShadowDecoration() {} eDecorationType CHyprDropShadowDecoration::getDecorationType() { return DECORATION_SHADOW; } SDecorationPositioningInfo CHyprDropShadowDecoration::getPositioningInfo() { - return {DECORATION_POSITION_ABSOLUTE}; + SDecorationPositioningInfo info; + info.policy = DECORATION_POSITION_ABSOLUTE; + info.desiredExtents = m_seExtents; + info.edges = DECORATION_EDGE_BOTTOM | DECORATION_EDGE_LEFT | DECORATION_EDGE_RIGHT | DECORATION_EDGE_TOP; + + m_seReportedExtents = m_seExtents; + return info; } void CHyprDropShadowDecoration::onPositioningReply(const SDecorationPositioningReply& reply) { @@ -148,8 +152,11 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D } else { g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a); } + + if (m_seExtents != m_seReportedExtents) + g_pDecorationPositioner->repositionDeco(this); } eDecorationLayer CHyprDropShadowDecoration::getDecorationLayer() { return DECORATION_LAYER_BOTTOM; -} \ No newline at end of file +} diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index 9f0f58a0..c3e362c7 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -23,6 +23,7 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { private: SWindowDecorationExtents m_seExtents; + SWindowDecorationExtents m_seReportedExtents; CWindow* m_pWindow = nullptr; diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index 98627d4c..55e5470d 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -226,11 +226,41 @@ SWindowDecorationExtents CDecorationPositioner::getWindowDecorationReserved(CWin } SWindowDecorationExtents CDecorationPositioner::getWindowDecorationExtents(CWindow* pWindow, bool inputOnly) { - if (!inputOnly) - return m_mWindowDatas[pWindow].extents; + CBox accum = pWindow->getWindowMainSurfaceBox().expand(pWindow->getRealBorderSize()); - // TODO: - return m_mWindowDatas[pWindow].extents; + for (auto& data : m_vWindowPositioningDatas) { + if (data->pWindow != pWindow) + continue; + + if (!(data->pDecoration->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT) && inputOnly) + continue; + + CBox decoBox; + + if (data->positioningInfo.policy == DECORATION_POSITION_ABSOLUTE) { + decoBox = data->pWindow->getWindowMainSurfaceBox(); + decoBox.addExtents(data->positioningInfo.desiredExtents); + } else { + decoBox = data->lastReply.assignedGeometry; + const auto EDGEPOINT = getEdgeDefinedPoint(data->positioningInfo.edges, pWindow); + decoBox.translate(EDGEPOINT); + } + + SWindowDecorationExtents extentsToAdd; + + if (decoBox.x < accum.x) + extentsToAdd.topLeft.x = accum.x - decoBox.x; + if (decoBox.y < accum.y) + extentsToAdd.topLeft.y = accum.y - decoBox.y; + if (decoBox.x + decoBox.w > accum.x + accum.w) + extentsToAdd.bottomRight.x = (decoBox.x + decoBox.w) - (accum.x + accum.w); + if (decoBox.y + decoBox.h > accum.y + accum.h) + extentsToAdd.bottomRight.y = (decoBox.y + decoBox.h) - (accum.y + accum.h); + + accum.addExtents(extentsToAdd); + } + + return accum.extentsFrom(pWindow->getWindowMainSurfaceBox()); } CBox CDecorationPositioner::getBoxWithIncludedDecos(CWindow* pWindow) { diff --git a/src/render/decorations/DecorationPositioner.hpp b/src/render/decorations/DecorationPositioner.hpp index 9fc45ba3..ebb9f480 100644 --- a/src/render/decorations/DecorationPositioner.hpp +++ b/src/render/decorations/DecorationPositioner.hpp @@ -27,7 +27,8 @@ enum eDecorationEdges Request the positioner to position a decoration DECORATION_POSITION_ABSOLUTE: - - desiredExtents may contain the extents to be used when reserved is set. Edges has to have the edges used. + - desiredExtents has to contain the extents. Edges has to have the edges used. + - reserved allowed DECORATION_POSITION_STICKY: - one edge allowed - priority allowed From 8180ca65a51e3dff571ab7bb32cba2262cea2897 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 11 Nov 2023 15:20:21 +0000 Subject: [PATCH 210/513] props: bump ver to 0.32.1 --- props.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/props.json b/props.json index 285025dd..43835aaf 100644 --- a/props.json +++ b/props.json @@ -1,3 +1,3 @@ { - "version": "0.32.0" + "version": "0.32.1" } \ No newline at end of file From db82fc5b09db7e80a6195cdc11ac4d05ad4d88f0 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 11 Nov 2023 15:23:33 +0000 Subject: [PATCH 211/513] animationmgr: push shadow avs to ended on disabled --- src/managers/AnimationManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index a5e1c47e..e292de29 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -68,6 +68,7 @@ void CAnimationManager::tick() { if (av->m_eDamagePolicy == AVARDAMAGE_SHADOW && !*PSHADOWSENABLED) { av->warp(false); + animationEndedVars.push_back(av); continue; } From 844da8db561f00f99d7e861b4b9a8bf51bbcd10c Mon Sep 17 00:00:00 2001 From: Dickby Date: Sat, 11 Nov 2023 16:43:31 +0100 Subject: [PATCH 212/513] shaders: Avoid calculating unused values in hsl2rgb. (#3827) --- src/render/shaders/Textures.hpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index daa7bc9b..8108f451 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -258,19 +258,18 @@ vec3 hsl2rgb(vec3 col) { float sat = col.y; float lum = col.z; - vec3 xt = vec3(rcpsixth * (hue - twothird), 0.0, rcpsixth * (1.0 - hue)); - - if (hue < twothird) { - xt.r = 0.0; - xt.g = rcpsixth * (twothird - hue); - xt.b = rcpsixth * (hue - onethird); - } + vec3 xt = vec3(0.0); if (hue < onethird) { xt.r = rcpsixth * (onethird - hue); xt.g = rcpsixth * hue; xt.b = 0.0; - } + } else if (hue < twothird) { + xt.r = 0.0; + xt.g = rcpsixth * (twothird - hue); + xt.b = rcpsixth * (hue - onethird); + } else + xt = vec3(rcpsixth * (hue - twothird), 0.0, rcpsixth * (1.0 - hue)); xt = min(xt, 1.0); From 52cf122a0a5e912b662fbb63e50c9e87bd0dc33c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 11 Nov 2023 16:15:11 +0000 Subject: [PATCH 213/513] shadow: move workspace offset calcs to draw fixes #3829 --- .../decorations/CHyprDropShadowDecoration.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 1990d37d..08234339 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -38,13 +38,8 @@ void CHyprDropShadowDecoration::damageEntire() { } void CHyprDropShadowDecoration::updateWindow(CWindow* pWindow) { - - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); - - const auto WORKSPACEOFFSET = PWORKSPACE && !pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D(); - - m_vLastWindowPos = pWindow->m_vRealPosition.vec() + WORKSPACEOFFSET; - m_vLastWindowSize = pWindow->m_vRealSize.vec(); + m_vLastWindowPos = m_pWindow->m_vRealPosition.vec(); + m_vLastWindowSize = m_pWindow->m_vRealSize.vec(); m_bLastWindowBox = {m_vLastWindowPos.x, m_vLastWindowPos.y, m_vLastWindowSize.x, m_vLastWindowSize.y}; m_bLastWindowBoxWithDecos = g_pDecorationPositioner->getBoxWithIncludedDecos(pWindow); @@ -76,11 +71,13 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D if (*PSHADOWS != 1) return; // disabled - const auto ROUNDING = m_pWindow->rounding() + m_pWindow->getRealBorderSize(); + const auto ROUNDING = m_pWindow->rounding() + m_pWindow->getRealBorderSize(); + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_pWindow->m_iWorkspaceID); + const auto WORKSPACEOFFSET = PWORKSPACE && !m_pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D(); // draw the shadow CBox fullBox = m_bLastWindowBoxWithDecos; - fullBox.translate(-pMonitor->vecPosition); + fullBox.translate(-pMonitor->vecPosition + WORKSPACEOFFSET); fullBox.x -= *PSHADOWSIZE; fullBox.y -= *PSHADOWSIZE; fullBox.w += 2 * *PSHADOWSIZE; @@ -114,8 +111,8 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D CBox withDecos = m_bLastWindowBoxWithDecos; // get window box - windowBox.translate(-pMonitor->vecPosition).scale(pMonitor->scale).round(); - withDecos.translate(-pMonitor->vecPosition).scale(pMonitor->scale).round(); + windowBox.translate(-pMonitor->vecPosition + WORKSPACEOFFSET).scale(pMonitor->scale).round(); + withDecos.translate(-pMonitor->vecPosition + WORKSPACEOFFSET).scale(pMonitor->scale).round(); auto scaledDecoExtents = withDecos.extentsFrom(windowBox).round(); From ae46fbafe5ba2d707e3d2897de74bf5a1d7397c6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 11 Nov 2023 17:13:20 +0000 Subject: [PATCH 214/513] xdg: set state maximized for all tiled windows forces them to not draw stupid decorations of their own. Wlroots stopped doing it for us. Fixes #3830 --- src/managers/XWaylandManager.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 04fcf967..f13b2cd2 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -184,8 +184,11 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f } void CHyprXWaylandManager::setWindowStyleTiled(CWindow* pWindow, uint32_t edgez) { - if (!pWindow->m_bIsX11) - wlr_xdg_toplevel_set_tiled(pWindow->m_uSurface.xdg->toplevel, edgez); + if (pWindow->m_bIsX11) + return; + + wlr_xdg_toplevel_set_tiled(pWindow->m_uSurface.xdg->toplevel, edgez); + wlr_xdg_toplevel_set_maximized(pWindow->m_uSurface.xdg->toplevel, true); } wlr_surface* CHyprXWaylandManager::surfaceAt(CWindow* pWindow, const Vector2D& client, Vector2D& surface) { From 6eb2abcb20b967daaeeb7f109005e9fa817bc70c Mon Sep 17 00:00:00 2001 From: Dickby Date: Sat, 11 Nov 2023 18:20:18 +0100 Subject: [PATCH 215/513] shaders: Small optimization in rgb2hsl. (#3831) --- src/render/shaders/Textures.hpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index 8108f451..e32712fa 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -238,14 +238,13 @@ vec3 rgb2hsl(vec3 col) { vec3 adds = vec3(((green - blue) / delta), 2.0 + ((blue - red) / delta), 4.0 + ((red - green) / delta)); - float deltaGtz = (delta > 0.0) ? 1.0 : 0.0; + if (delta > 0.0) { + hue += dot(adds, masks); + hue /= 6.0; - hue += dot(adds, masks); - hue *= deltaGtz; - hue /= 6.0; - - if (hue < 0.0) - hue += 1.0; + if (hue < 0.0) + hue += 1.0; + } return vec3(hue, sat, lum); } From eab279984285250bd544de40868888186a8edeb7 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 11 Nov 2023 17:24:04 +0000 Subject: [PATCH 216/513] props: bump ver to 0.32.2 --- props.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/props.json b/props.json index 43835aaf..3eb986de 100644 --- a/props.json +++ b/props.json @@ -1,3 +1,3 @@ { - "version": "0.32.1" + "version": "0.32.2" } \ No newline at end of file From f39a6ca17c3abd9ce472e4cf5fd96df462969c4f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 11 Nov 2023 18:07:56 +0000 Subject: [PATCH 217/513] decoration-positioner: improve stability --- .../decorations/DecorationPositioner.cpp | 44 +++++++++++++++++-- .../decorations/DecorationPositioner.hpp | 8 ++-- 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index 55e5470d..62279ca5 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -6,6 +6,11 @@ CDecorationPositioner::CDecorationPositioner() { auto* const PWINDOW = std::any_cast(data); this->onWindowUnmap(PWINDOW); }); + + g_pHookSystem->hookDynamic("openWindow", [this](void* call, SCallbackInfo& info, std::any data) { + auto* const PWINDOW = std::any_cast(data); + this->onWindowMap(PWINDOW); + }); } Vector2D CDecorationPositioner::getEdgeDefinedPoint(uint32_t edges, CWindow* pWindow) { @@ -52,7 +57,12 @@ Vector2D CDecorationPositioner::getEdgeDefinedPoint(uint32_t edges, CWindow* pWi void CDecorationPositioner::uncacheDecoration(IHyprWindowDecoration* deco) { std::erase_if(m_vWindowPositioningDatas, [&](const auto& data) { return data->pDecoration == deco; }); - m_mWindowDatas[deco->m_pWindow].needsRecalc = true; + + const auto WIT = std::find_if(m_mWindowDatas.begin(), m_mWindowDatas.end(), [&](const auto& other) { return other.first == deco->m_pWindow; }); + if (WIT == m_mWindowDatas.end()) + return; + + WIT->second.needsRecalc = true; } void CDecorationPositioner::repositionDeco(IHyprWindowDecoration* deco) { @@ -73,11 +83,29 @@ CDecorationPositioner::SWindowPositioningData* CDecorationPositioner::getDataFor return DATA; } +void CDecorationPositioner::sanitizeDatas() { + std::erase_if(m_mWindowDatas, [](const auto& other) { return !g_pCompositor->windowValidMapped(other.first); }); + std::erase_if(m_vWindowPositioningDatas, [](const auto& other) { + if (!g_pCompositor->windowValidMapped(other->pWindow)) + return true; + if (std::find_if(other->pWindow->m_dWindowDecorations.begin(), other->pWindow->m_dWindowDecorations.end(), + [&](const auto& el) { return el.get() == other->pDecoration; }) == other->pWindow->m_dWindowDecorations.end()) + return true; + return false; + }); +} + void CDecorationPositioner::onWindowUpdate(CWindow* pWindow) { if (!g_pCompositor->windowValidMapped(pWindow)) return; - auto* const WINDOWDATA = &m_mWindowDatas[pWindow]; + const auto WIT = std::find_if(m_mWindowDatas.begin(), m_mWindowDatas.end(), [&](const auto& other) { return other.first == pWindow; }); + if (WIT == m_mWindowDatas.end()) + return; + + const auto WINDOWDATA = &WIT->second; + + sanitizeDatas(); // std::vector datas; @@ -221,8 +249,15 @@ void CDecorationPositioner::onWindowUnmap(CWindow* pWindow) { m_mWindowDatas.erase(pWindow); } +void CDecorationPositioner::onWindowMap(CWindow* pWindow) { + m_mWindowDatas[pWindow] = {}; +} + SWindowDecorationExtents CDecorationPositioner::getWindowDecorationReserved(CWindow* pWindow) { - return m_mWindowDatas[pWindow].reserved; + try { + const auto E = m_mWindowDatas.at(pWindow); + return E.reserved; + } catch (std::out_of_range& e) { return {}; } } SWindowDecorationExtents CDecorationPositioner::getWindowDecorationExtents(CWindow* pWindow, bool inputOnly) { @@ -232,6 +267,9 @@ SWindowDecorationExtents CDecorationPositioner::getWindowDecorationExtents(CWind if (data->pWindow != pWindow) continue; + if (!data->pWindow || !data->pDecoration) + continue; + if (!(data->pDecoration->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT) && inputOnly) continue; diff --git a/src/render/decorations/DecorationPositioner.hpp b/src/render/decorations/DecorationPositioner.hpp index ebb9f480..fca8eec2 100644 --- a/src/render/decorations/DecorationPositioner.hpp +++ b/src/render/decorations/DecorationPositioner.hpp @@ -9,14 +9,12 @@ class CWindow; class IHyprWindowDecoration; -enum eDecorationPositioningPolicy -{ +enum eDecorationPositioningPolicy { DECORATION_POSITION_ABSOLUTE = 0, /* Decoration does not interfere with anything else */ DECORATION_POSITION_STICKY, /* Decoration is stuck to some edge of a window */ }; -enum eDecorationEdges -{ +enum eDecorationEdges { DECORATION_EDGE_TOP = 1 << 0, DECORATION_EDGE_BOTTOM = 1 << 1, DECORATION_EDGE_LEFT = 1 << 2, @@ -93,6 +91,8 @@ class CDecorationPositioner { SWindowPositioningData* getDataFor(IHyprWindowDecoration* pDecoration, CWindow* pWindow); void onWindowUnmap(CWindow* pWindow); + void onWindowMap(CWindow* pWindow); + void sanitizeDatas(); }; inline std::unique_ptr g_pDecorationPositioner; \ No newline at end of file From 9afdd61adeaf413afbe853dbc5fdf6853c8bde21 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 11 Nov 2023 18:14:46 +0000 Subject: [PATCH 218/513] props: bump ver to 0.32.3 --- props.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/props.json b/props.json index 3eb986de..3068f9ca 100644 --- a/props.json +++ b/props.json @@ -1,3 +1,3 @@ { - "version": "0.32.2" + "version": "0.32.3" } \ No newline at end of file From 91cbe93cf875c064847c76c6501d2a22c3f0abec Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 12 Nov 2023 13:01:23 +0000 Subject: [PATCH 219/513] decoration: add NON_SOLID flag for shadow fixes #3841 --- .../decorations/CHyprDropShadowDecoration.cpp | 4 +++ .../decorations/CHyprDropShadowDecoration.hpp | 2 ++ .../decorations/DecorationPositioner.cpp | 32 ++++++++++++------- .../decorations/DecorationPositioner.hpp | 8 +++-- .../decorations/IHyprWindowDecoration.hpp | 1 + 5 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 08234339..c992a4d8 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -26,6 +26,10 @@ void CHyprDropShadowDecoration::onPositioningReply(const SDecorationPositioningR updateWindow(m_pWindow); } +uint64_t CHyprDropShadowDecoration::getDecorationFlags() { + return DECORATION_NON_SOLID; +} + void CHyprDropShadowDecoration::damageEntire() { static auto* const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue; diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index c3e362c7..7820a76c 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -21,6 +21,8 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { virtual eDecorationLayer getDecorationLayer(); + virtual uint64_t getDecorationFlags(); + private: SWindowDecorationExtents m_seExtents; SWindowDecorationExtents m_seReportedExtents; diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index 62279ca5..840fd907 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -168,16 +168,20 @@ void CDecorationPositioner::onWindowUpdate(CWindow* pWindow) { const bool LEFT = wd->positioningInfo.edges & DECORATION_EDGE_LEFT; const bool RIGHT = wd->positioningInfo.edges & DECORATION_EDGE_RIGHT; const int EDGESNO = TOP + BOTTOM + LEFT + RIGHT; + const bool SOLID = !(wd->pDecoration->getDecorationFlags() & DECORATION_NON_SOLID); if (wd->positioningInfo.policy == DECORATION_POSITION_ABSOLUTE) { - if (LEFT) - stickyOffsetXL += wd->positioningInfo.desiredExtents.topLeft.x; - if (RIGHT) - stickyOffsetXR += wd->positioningInfo.desiredExtents.bottomRight.x; - if (TOP) - stickyOffsetYT += wd->positioningInfo.desiredExtents.topLeft.y; - if (BOTTOM) - stickyOffsetYB += wd->positioningInfo.desiredExtents.bottomRight.y; + + if (SOLID) { + if (LEFT) + stickyOffsetXL += wd->positioningInfo.desiredExtents.topLeft.x; + if (RIGHT) + stickyOffsetXR += wd->positioningInfo.desiredExtents.bottomRight.x; + if (TOP) + stickyOffsetYT += wd->positioningInfo.desiredExtents.topLeft.y; + if (BOTTOM) + stickyOffsetYB += wd->positioningInfo.desiredExtents.bottomRight.y; + } wd->lastReply = {}; wd->pDecoration->onPositioningReply({}); @@ -210,23 +214,27 @@ void CDecorationPositioner::onWindowUpdate(CWindow* pWindow) { pos.x -= desiredSize; size = {desiredSize, wb.size().y}; - stickyOffsetXL += desiredSize; + if (SOLID) + stickyOffsetXL += desiredSize; } else if (RIGHT) { pos = wb.pos() + Vector2D{wb.size().x, 0} - EDGEPOINT + Vector2D{stickyOffsetXR, 0}; size = {desiredSize, wb.size().y}; - stickyOffsetXR += desiredSize; + if (SOLID) + stickyOffsetXR += desiredSize; } else if (TOP) { pos = wb.pos() - EDGEPOINT - Vector2D{0, stickyOffsetYT}; pos.y -= desiredSize; size = {wb.size().x, desiredSize}; - stickyOffsetYT += desiredSize; + if (SOLID) + stickyOffsetYT += desiredSize; } else { pos = wb.pos() + Vector2D{0, wb.size().y} - EDGEPOINT - Vector2D{0, stickyOffsetYB}; size = {wb.size().x, desiredSize}; - stickyOffsetYB += desiredSize; + if (SOLID) + stickyOffsetYB += desiredSize; } wd->lastReply = {{pos, size}, EPHEMERAL}; diff --git a/src/render/decorations/DecorationPositioner.hpp b/src/render/decorations/DecorationPositioner.hpp index fca8eec2..ae4a814a 100644 --- a/src/render/decorations/DecorationPositioner.hpp +++ b/src/render/decorations/DecorationPositioner.hpp @@ -9,12 +9,14 @@ class CWindow; class IHyprWindowDecoration; -enum eDecorationPositioningPolicy { - DECORATION_POSITION_ABSOLUTE = 0, /* Decoration does not interfere with anything else */ +enum eDecorationPositioningPolicy +{ + DECORATION_POSITION_ABSOLUTE = 0, /* Decoration wants absolute positioning */ DECORATION_POSITION_STICKY, /* Decoration is stuck to some edge of a window */ }; -enum eDecorationEdges { +enum eDecorationEdges +{ DECORATION_EDGE_TOP = 1 << 0, DECORATION_EDGE_BOTTOM = 1 << 1, DECORATION_EDGE_LEFT = 1 << 2, diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp index 15890f44..c411a4d9 100644 --- a/src/render/decorations/IHyprWindowDecoration.hpp +++ b/src/render/decorations/IHyprWindowDecoration.hpp @@ -24,6 +24,7 @@ enum eDecorationFlags { DECORATION_ALLOWS_MOUSE_INPUT = 1 << 0, /* this decoration accepts mouse input */ DECORATION_PART_OF_MAIN_WINDOW = 1 << 1, /* this decoration is a *seamless* part of the main window, so stuff like shadows will include it */ + DECORATION_NON_SOLID = 1 << 2, /* this decoration is not solid. Other decorations should draw on top of it. Example: shadow */ }; class CWindow; From 1bfd4a2bff5f67872b868d519fbb45b32aa72b1f Mon Sep 17 00:00:00 2001 From: Alessio Molinari Date: Sun, 12 Nov 2023 14:14:05 +0100 Subject: [PATCH 220/513] output-layout: fix wlroots display handling (#3718) --- src/Compositor.cpp | 2 +- src/events/Monitors.cpp | 7 +++++-- src/helpers/Monitor.cpp | 8 ++++---- src/helpers/Monitor.hpp | 2 +- src/render/Renderer.cpp | 13 +++++++++++-- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 29d019c1..70a19cb5 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2792,4 +2792,4 @@ void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scal void CCompositor::setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform) { wlr_surface_set_preferred_buffer_transform(pSurface, transform); -} \ No newline at end of file +} diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 9155fe87..13f3f829 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -22,10 +22,13 @@ void Events::listener_change(wl_listener* listener, void* data) { if (!CONFIG) return; - for (auto& m : g_pCompositor->m_vMonitors) { + for (auto& m : g_pCompositor->m_vRealMonitors) { if (!m->output) continue; + if (g_pCompositor->m_pUnsafeOutput == m.get()) + continue; + const auto CONFIGHEAD = wlr_output_configuration_head_v1_create(CONFIG, m->output); CBox BOX; @@ -195,7 +198,7 @@ void Events::listener_monitorDestroy(void* owner, void* data) { Debug::log(LOG, "Destroy called for monitor {}", pMonitor->output->name); - pMonitor->onDisconnect(); + pMonitor->onDisconnect(true); pMonitor->output = nullptr; pMonitor->m_bRenderingInitPassed = false; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 9dbd2a3e..743c938e 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -188,7 +188,7 @@ void CMonitor::onConnect(bool noRule) { g_pCompositor->scheduleFrameForMonitor(this); } -void CMonitor::onDisconnect() { +void CMonitor::onDisconnect(bool destroy) { if (renderTimer) { wl_event_source_remove(renderTimer); @@ -276,7 +276,8 @@ void CMonitor::onDisconnect() { activeWorkspace = -1; - wlr_output_layout_remove(g_pCompositor->m_sWLROutputLayout, output); + if (!destroy) + wlr_output_layout_remove(g_pCompositor->m_sWLROutputLayout, output); wlr_output_enable(output, false); @@ -298,7 +299,6 @@ void CMonitor::onDisconnect() { g_pHyprRenderer->m_pMostHzMonitor = pMonitorMostHz; } - std::erase_if(g_pCompositor->m_vMonitors, [&](std::shared_ptr& el) { return el.get() == this; }); } @@ -642,4 +642,4 @@ void CMonitor::moveTo(const Vector2D& pos) { Vector2D CMonitor::middle() { return vecPosition + vecSize / 2.f; -} \ No newline at end of file +} diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 10790b5e..2aa7e7eb 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -110,7 +110,7 @@ class CMonitor { // methods void onConnect(bool noRule); - void onDisconnect(); + void onDisconnect(bool destroy = false); void addDamage(const pixman_region32_t* rg); void addDamage(const CRegion* rg); void addDamage(const CBox* box); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 98dcf7f5..65aa7138 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2,6 +2,7 @@ #include "../Compositor.hpp" #include "linux-dmabuf-unstable-v1-protocol.h" #include "../helpers/Region.hpp" +#include CHyprRenderer::CHyprRenderer() { const auto ENV = getenv("WLR_DRM_NO_ATOMIC"); @@ -1287,13 +1288,22 @@ void CHyprRenderer::outputMgrApplyTest(wlr_output_configuration_v1* config, bool break; } - if (!test) + if (!test) { g_pConfigManager->m_bWantsMonitorReload = true; // for monitor keywords + // if everything is disabled, performMonitorReload won't be called from renderMonitor + bool allDisabled = std::all_of(g_pCompositor->m_vMonitors.begin(), g_pCompositor->m_vMonitors.end(), + [](const auto m) { return !m->m_bEnabled || g_pCompositor->m_pUnsafeOutput == m.get(); }); + if (allDisabled) { + Debug::log(LOG, "OutputMgr apply: All monitors disabled; performing monitor reload."); + g_pConfigManager->performMonitorReload(); + } + } if (ok) wlr_output_configuration_v1_send_succeeded(config); else wlr_output_configuration_v1_send_failed(config); + wlr_output_configuration_v1_destroy(config); Debug::log(LOG, "OutputMgr Applied/Tested."); @@ -1645,7 +1655,6 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR // if it's disabled, disable and ignore if (pMonitorRule->disabled) { - if (pMonitor->m_bEnabled) pMonitor->onDisconnect(); From 69e314207d193eb67be0ae153d50c6c6bcee4b60 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 12 Nov 2023 13:34:42 +0000 Subject: [PATCH 221/513] internal: replace INT_MAX with WORKSPACE_INVALID --- src/config/ConfigManager.cpp | 4 ++-- src/events/Windows.cpp | 2 +- src/helpers/MiscFunctions.cpp | 16 +++++++--------- src/helpers/Monitor.cpp | 2 +- src/macros.hpp | 2 ++ src/managers/KeybindManager.cpp | 12 ++++++------ src/managers/input/Swipe.cpp | 2 +- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index d07e6a6a..424b67a4 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1164,13 +1164,13 @@ void CConfigManager::handleWorkspaceRules(const std::string& command, const std: auto rules = value.substr(FIRST_DELIM + 1); SWorkspaceRule wsRule; wsRule.workspaceString = first_ident; - if (id == INT_MAX) { + if (id == WORKSPACE_INVALID) { // it could be the monitor. If so, second value MUST be // the workspace. const auto WORKSPACE_DELIM = value.find_first_of(',', FIRST_DELIM + 1); auto wsIdent = removeBeginEndSpacesTabs(value.substr(FIRST_DELIM + 1, (WORKSPACE_DELIM - FIRST_DELIM - 1))); id = getWorkspaceIDFromString(wsIdent, name); - if (id == INT_MAX) { + if (id == WORKSPACE_INVALID) { Debug::log(ERR, "Invalid workspace identifier found: {}", wsIdent); parseError = "Invalid workspace identifier found: " + wsIdent; return; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 00d78f4c..1d5384b7 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -279,7 +279,7 @@ void Events::listener_mapWindow(void* owner, void* data) { std::string requestedWorkspaceName; const int REQUESTEDWORKSPACEID = getWorkspaceIDFromString(WORKSPACEARGS.join(" ", 0, workspaceSilent ? WORKSPACEARGS.size() - 1 : 0), requestedWorkspaceName); - if (REQUESTEDWORKSPACEID != INT_MAX) { + if (REQUESTEDWORKSPACEID != WORKSPACE_INVALID) { auto pWorkspace = g_pCompositor->getWorkspaceByID(REQUESTEDWORKSPACEID); if (!pWorkspace) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 376ac032..7a9c5e5e 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -247,7 +247,7 @@ bool isDirection(const char& arg) { } int getWorkspaceIDFromString(const std::string& in, std::string& outName) { - int result = INT_MAX; + int result = WORKSPACE_INVALID; if (in.starts_with("special")) { outName = "special"; @@ -280,17 +280,17 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { } } else if (in.starts_with("prev")) { if (!g_pCompositor->m_pLastMonitor) - return INT_MAX; + return WORKSPACE_INVALID; const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(g_pCompositor->m_pLastMonitor->activeWorkspace); if (!PWORKSPACE) - return INT_MAX; + return WORKSPACE_INVALID; const auto PLASTWORKSPACE = g_pCompositor->getWorkspaceByID(PWORKSPACE->m_sPrevWorkspace.iID); if (!PLASTWORKSPACE) - return INT_MAX; + return WORKSPACE_INVALID; outName = PLASTWORKSPACE->m_szName; return PLASTWORKSPACE->m_iID; @@ -298,8 +298,7 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { if (in[0] == 'r' && (in[1] == '-' || in[1] == '+') && isNumber(in.substr(2))) { if (!g_pCompositor->m_pLastMonitor) { Debug::log(ERR, "Relative monitor workspace on monitor null!"); - result = INT_MAX; - return result; + return WORKSPACE_INVALID; } result = (int)getPlusMinusKeywordResult(in.substr(1), 0); @@ -433,8 +432,7 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { if (!g_pCompositor->m_pLastMonitor) { Debug::log(ERR, "Relative monitor workspace on monitor null!"); - result = INT_MAX; - return result; + return WORKSPACE_INVALID; } // monitor relative @@ -483,7 +481,7 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { result = std::max((int)getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace), 1); else { Debug::log(ERR, "Relative workspace on no mon!"); - result = INT_MAX; + return WORKSPACE_INVALID; } } else if (isNumber(in)) result = std::max(std::stoi(in), 1); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 743c938e..20880d8d 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -353,7 +353,7 @@ void CMonitor::setupDefaultWS(const SMonitorRule& monitorRule) { findAvailableDefaultWS() : getWorkspaceIDFromString(g_pConfigManager->getDefaultWorkspaceFor(szName), newDefaultWorkspaceName); - if (WORKSPACEID == INT_MAX || (WORKSPACEID >= SPECIAL_WORKSPACE_START && WORKSPACEID <= -2)) { + if (WORKSPACEID == WORKSPACE_INVALID || (WORKSPACEID >= SPECIAL_WORKSPACE_START && WORKSPACEID <= -2)) { WORKSPACEID = g_pCompositor->m_vWorkspaces.size() + 1; newDefaultWorkspaceName = std::to_string(WORKSPACEID); diff --git a/src/macros.hpp b/src/macros.hpp index eada3a9f..c2eb98db 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -22,6 +22,8 @@ #define STRVAL_EMPTY "[[EMPTY]]" +#define WORKSPACE_INVALID -1L + #define LISTENER(name) \ void listener_##name(wl_listener*, void*); \ inline wl_listener listen_##name = {.notify = listener_##name} diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index e4cac5f4..d8307de2 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -831,7 +831,7 @@ void CKeybindManager::changeworkspace(std::string args) { workspaceToChangeTo = getWorkspaceIDFromString(args, workspaceName); } - if (workspaceToChangeTo == INT_MAX) { + if (workspaceToChangeTo == WORKSPACE_INVALID) { Debug::log(ERR, "Error in changeworkspace, invalid value"); return; } @@ -920,7 +920,7 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) { std::string workspaceName; const auto WORKSPACEID = getWorkspaceIDFromString(args, workspaceName); - if (WORKSPACEID == INT_MAX) { + if (WORKSPACEID == WORKSPACE_INVALID) { Debug::log(LOG, "Invalid workspace in moveActiveToWorkspace"); return; } @@ -977,7 +977,7 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { const int WORKSPACEID = getWorkspaceIDFromString(args, workspaceName); - if (WORKSPACEID == INT_MAX) { + if (WORKSPACEID == WORKSPACE_INVALID) { Debug::log(ERR, "Error in moveActiveToWorkspaceSilent, invalid value"); return; } @@ -1233,7 +1233,7 @@ void CKeybindManager::alterSplitRatio(std::string args) { } } - if (splitratio == INT_MAX) { + if (splitratio == WORKSPACE_INVALID) { Debug::log(ERR, "Splitratio invalid in alterSplitRatio!"); return; } @@ -1425,7 +1425,7 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) { std::string workspaceName; const int WORKSPACEID = getWorkspaceIDFromString(workspace, workspaceName); - if (WORKSPACEID == INT_MAX) { + if (WORKSPACEID == WORKSPACE_INVALID) { Debug::log(ERR, "moveWorkspaceToMonitor invalid workspace!"); return; } @@ -1447,7 +1447,7 @@ void CKeybindManager::toggleSpecialWorkspace(std::string args) { std::string workspaceName = ""; int workspaceID = getWorkspaceIDFromString("special:" + args, workspaceName); - if (workspaceID == INT_MAX || !g_pCompositor->isWorkspaceSpecial(workspaceID)) { + if (workspaceID == WORKSPACE_INVALID || !g_pCompositor->isWorkspaceSpecial(workspaceID)) { Debug::log(ERR, "Invalid workspace passed to special"); return; } diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index 360397eb..dba3d735 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -211,7 +211,7 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { auto workspaceIDLeft = getWorkspaceIDFromString(*PSWIPENUMBER ? "-1" : (*PSWIPEUSER ? "r-1" : "m-1"), wsname); auto workspaceIDRight = getWorkspaceIDFromString(*PSWIPENUMBER ? "+1" : (*PSWIPEUSER ? "r+1" : "m+1"), wsname); - if ((workspaceIDLeft == INT_MAX || workspaceIDRight == INT_MAX || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID) && !*PSWIPENEW) { + if ((workspaceIDLeft == WORKSPACE_INVALID || workspaceIDRight == WORKSPACE_INVALID || workspaceIDLeft == m_sActiveSwipe.pWorkspaceBegin->m_iID) && !*PSWIPENEW) { m_sActiveSwipe.pWorkspaceBegin = nullptr; // invalidate the swipe return; } From 65efde32c99b8119d3c55729508b92801b60cc13 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 12 Nov 2023 13:40:02 +0000 Subject: [PATCH 222/513] internal: make getPlusMinusKeywordResult return optional --- src/helpers/MiscFunctions.cpp | 29 ++++++++++++++++++++++------- src/helpers/MiscFunctions.hpp | 2 +- src/managers/KeybindManager.cpp | 26 +++++++++----------------- 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 7a9c5e5e..85a81657 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -204,12 +204,12 @@ std::string removeBeginEndSpacesTabs(std::string str) { return str; } -float getPlusMinusKeywordResult(std::string source, float relative) { +std::optional getPlusMinusKeywordResult(std::string source, float relative) { try { return relative + stof(source); } catch (...) { Debug::log(ERR, "Invalid arg \"{}\" in getPlusMinusKeywordResult!", source); - return INT_MAX; + return {}; } } @@ -300,7 +300,13 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { Debug::log(ERR, "Relative monitor workspace on monitor null!"); return WORKSPACE_INVALID; } - result = (int)getPlusMinusKeywordResult(in.substr(1), 0); + + const auto PLUSMINUSRESULT = getPlusMinusKeywordResult(in.substr(1), 0); + + if (!PLUSMINUSRESULT.has_value()) + return WORKSPACE_INVALID; + + result = (int)PLUSMINUSRESULT.value(); int remains = (int)result; @@ -436,7 +442,12 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { } // monitor relative - result = (int)getPlusMinusKeywordResult(in.substr(1), 0); + const auto PLUSMINUSRESULT = getPlusMinusKeywordResult(in.substr(1), 0); + + if (!PLUSMINUSRESULT.has_value()) + return WORKSPACE_INVALID; + + result = (int)PLUSMINUSRESULT.value(); // result now has +/- what we should move on mon int remains = (int)result; @@ -477,9 +488,13 @@ int getWorkspaceIDFromString(const std::string& in, std::string& outName) { outName = g_pCompositor->getWorkspaceByID(validWSes[currentItem])->m_szName; } else { if (in[0] == '+' || in[0] == '-') { - if (g_pCompositor->m_pLastMonitor) - result = std::max((int)getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace), 1); - else { + if (g_pCompositor->m_pLastMonitor) { + const auto PLUSMINUSRESULT = getPlusMinusKeywordResult(in, g_pCompositor->m_pLastMonitor->activeWorkspace); + if (!PLUSMINUSRESULT.has_value()) + return WORKSPACE_INVALID; + + result = std::max((int)PLUSMINUSRESULT.value(), 1); + } else { Debug::log(ERR, "Relative workspace on no mon!"); return WORKSPACE_INVALID; } diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index b2fe5858..90479121 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -27,7 +27,7 @@ void logSystemInfo(); std::string execAndGet(const char*); int64_t getPPIDof(int64_t pid); int64_t configStringToInt(const std::string&); -float getPlusMinusKeywordResult(std::string in, float relative); +std::optional getPlusMinusKeywordResult(std::string in, float relative); void matrixProjection(float mat[9], int w, int h, wl_output_transform tr); double normalizeAngleRad(double ang); std::string replaceInString(std::string subject, const std::string& search, const std::string& replace); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index d8307de2..553872a5 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1216,24 +1216,16 @@ void CKeybindManager::toggleSplit(std::string args) { } void CKeybindManager::alterSplitRatio(std::string args) { - float splitratio = 0; - bool exact = false; + std::optional splitResult; + bool exact = false; - if (args == "+" || args == "-") { - Debug::log(LOG, "alterSplitRatio: using LEGACY +/-, consider switching to the Hyprland syntax."); - splitratio = (args == "+" ? 0.05f : -0.05f); - } + if (args.starts_with("exact")) { + exact = true; + splitResult = getPlusMinusKeywordResult(args.substr(5), 0); + } else + splitResult = getPlusMinusKeywordResult(args, 0); - if (splitratio == 0) { - if (args.starts_with("exact")) { - exact = true; - splitratio = getPlusMinusKeywordResult(args.substr(5), 0); - } else { - splitratio = getPlusMinusKeywordResult(args, 0); - } - } - - if (splitratio == WORKSPACE_INVALID) { + if (!splitResult.has_value()) { Debug::log(ERR, "Splitratio invalid in alterSplitRatio!"); return; } @@ -1243,7 +1235,7 @@ void CKeybindManager::alterSplitRatio(std::string args) { if (!PLASTWINDOW) return; - g_pLayoutManager->getCurrentLayout()->alterSplitRatio(PLASTWINDOW, splitratio, exact); + g_pLayoutManager->getCurrentLayout()->alterSplitRatio(PLASTWINDOW, splitResult.value(), exact); } void CKeybindManager::focusMonitor(std::string arg) { From 47d46aa56cc9c0c853401275bbe920e902f7d5e6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 12 Nov 2023 14:03:46 +0000 Subject: [PATCH 223/513] inputmgr: clean lists in ~dtor ref #3558 --- src/managers/input/InputManager.cpp | 12 ++++++++++++ src/managers/input/InputManager.hpp | 11 ++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index d096ab32..2dba7515 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -3,6 +3,18 @@ #include "wlr/types/wlr_switch.h" #include +CInputManager::~CInputManager() { + m_lConstraints.clear(); + m_lKeyboards.clear(); + m_lMice.clear(); + m_lTablets.clear(); + m_lTabletTools.clear(); + m_lTabletPads.clear(); + m_lIdleInhibitors.clear(); + m_lTouchDevices.clear(); + m_lSwitches.clear(); +} + void CInputManager::onMouseMoved(wlr_pointer_motion_event* e) { static auto* const PSENS = &g_pConfigManager->getConfigValuePtr("general:sensitivity")->floatValue; static auto* const PNOACCEL = &g_pConfigManager->getConfigValuePtr("input:force_no_accel")->intValue; diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 554f91db..b6d9d89c 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -7,12 +7,14 @@ #include "../../helpers/Timer.hpp" #include "InputMethodRelay.hpp" -enum eClickBehaviorMode { +enum eClickBehaviorMode +{ CLICKMODE_DEFAULT = 0, CLICKMODE_KILL }; -enum eMouseBindMode { +enum eMouseBindMode +{ MBIND_INVALID = -1, MBIND_MOVE = 0, MBIND_RESIZE = 1, @@ -20,7 +22,8 @@ enum eMouseBindMode { MBIND_RESIZE_FORCE_RATIO = 3 }; -enum eBorderIconDirection { +enum eBorderIconDirection +{ BORDERICON_NONE, BORDERICON_UP, BORDERICON_DOWN, @@ -61,6 +64,8 @@ class CKeybindManager; class CInputManager { public: + ~CInputManager(); + void onMouseMoved(wlr_pointer_motion_event*); void onMouseWarp(wlr_pointer_motion_absolute_event*); void onMouseButton(wlr_pointer_button_event*); From e974d1fe98087c7eff333345f58155437ca529cd Mon Sep 17 00:00:00 2001 From: Dickby Date: Sun, 12 Nov 2023 17:20:23 +0100 Subject: [PATCH 224/513] shaders: Some more changes in rgb2hsl. (#3834) --- src/render/shaders/Textures.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/render/shaders/Textures.hpp b/src/render/shaders/Textures.hpp index e32712fa..e78f39fc 100644 --- a/src/render/shaders/Textures.hpp +++ b/src/render/shaders/Textures.hpp @@ -234,11 +234,11 @@ vec3 rgb2hsl(vec3 col) { sat = delta / (mul * 2.0); } - vec3 masks = vec3((maxc == red && maxc != green) ? 1.0 : 0.0, (maxc == green && maxc != blue) ? 1.0 : 0.0, (maxc == blue && maxc != red) ? 1.0 : 0.0); - - vec3 adds = vec3(((green - blue) / delta), 2.0 + ((blue - red) / delta), 4.0 + ((red - green) / delta)); - if (delta > 0.0) { + vec3 maxcVec = vec3(maxc); + vec3 masks = vec3(equal(maxcVec, col)) * vec3(notEqual(maxcVec, vec3(green, blue, red))); + vec3 adds = vec3(0.0, 2.0, 4.0) + vec3(green - blue, blue - red, red - green) / delta; + hue += dot(adds, masks); hue /= 6.0; @@ -248,6 +248,7 @@ vec3 rgb2hsl(vec3 col) { return vec3(hue, sat, lum); } + vec3 hsl2rgb(vec3 col) { const float onethird = 1.0 / 3.0; const float twothird = 2.0 / 3.0; From 0ba2e6870478bcf1af1b6508677b46a3484fb21f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 12 Nov 2023 17:02:31 +0000 Subject: [PATCH 225/513] deco-positioner: don't remove hidden windows' data --- src/render/decorations/DecorationPositioner.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index 840fd907..937eaa9a 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -84,9 +84,9 @@ CDecorationPositioner::SWindowPositioningData* CDecorationPositioner::getDataFor } void CDecorationPositioner::sanitizeDatas() { - std::erase_if(m_mWindowDatas, [](const auto& other) { return !g_pCompositor->windowValidMapped(other.first); }); + std::erase_if(m_mWindowDatas, [](const auto& other) { return !g_pCompositor->windowExists(other.first); }); std::erase_if(m_vWindowPositioningDatas, [](const auto& other) { - if (!g_pCompositor->windowValidMapped(other->pWindow)) + if (!g_pCompositor->windowExists(other->pWindow)) return true; if (std::find_if(other->pWindow->m_dWindowDecorations.begin(), other->pWindow->m_dWindowDecorations.end(), [&](const auto& el) { return el.get() == other->pDecoration; }) == other->pWindow->m_dWindowDecorations.end()) @@ -96,7 +96,7 @@ void CDecorationPositioner::sanitizeDatas() { } void CDecorationPositioner::onWindowUpdate(CWindow* pWindow) { - if (!g_pCompositor->windowValidMapped(pWindow)) + if (!g_pCompositor->windowExists(pWindow) || !pWindow->m_bIsMapped) return; const auto WIT = std::find_if(m_mWindowDatas.begin(), m_mWindowDatas.end(), [&](const auto& other) { return other.first == pWindow; }); From 45e86d4fdf425452a39010de582081c466657045 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 12 Nov 2023 22:40:21 +0000 Subject: [PATCH 226/513] groupbar: translate box by workspace offset --- src/render/decorations/CHyprGroupBarDecoration.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 625888da..8f134c49 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -405,5 +405,13 @@ uint64_t CHyprGroupBarDecoration::getDecorationFlags() { CBox CHyprGroupBarDecoration::assignedBoxGlobal() { CBox box = m_bAssignedBox; - return box.translate(g_pDecorationPositioner->getEdgeDefinedPoint(DECORATION_EDGE_TOP, m_pWindow)); + box.translate(g_pDecorationPositioner->getEdgeDefinedPoint(DECORATION_EDGE_TOP, m_pWindow)); + + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_pWindow->m_iWorkspaceID); + + if (!PWORKSPACE) + return box; + + const auto WORKSPACEOFFSET = PWORKSPACE && !m_pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D(); + return box.translate(WORKSPACEOFFSET); } \ No newline at end of file From 824ccd957b422e010d1c0d55961ed98386bb19b6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 12 Nov 2023 22:59:19 +0000 Subject: [PATCH 227/513] renderer: pass proper arg to main param of uv calcs was fucking up some non-fitting subsurfaces --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 65aa7138..ad3046e3 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -66,7 +66,7 @@ void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { if (windowBox.width <= 1 || windowBox.height <= 1) return; // invisible - g_pHyprRenderer->calculateUVForSurface(RDATA->pWindow, surface, RDATA->squishOversized); + g_pHyprRenderer->calculateUVForSurface(RDATA->pWindow, surface, RDATA->surface == surface); windowBox.scale(RDATA->pMonitor->scale); windowBox.round(); From ba5bc5871fb015a8fb55ff6991bc951f677a2a4f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 12 Nov 2023 23:06:31 +0000 Subject: [PATCH 228/513] subsurfaces: damage window on subsurface size change --- src/helpers/SubsurfaceTree.cpp | 10 +++++++++- src/helpers/SubsurfaceTree.hpp | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/helpers/SubsurfaceTree.cpp b/src/helpers/SubsurfaceTree.cpp index c10d45e1..5891411b 100644 --- a/src/helpers/SubsurfaceTree.cpp +++ b/src/helpers/SubsurfaceTree.cpp @@ -220,6 +220,8 @@ void Events::listener_commitSubsurface(void* owner, void* data) { // no damaging if it's not visible if (!g_pHyprRenderer->shouldRenderWindow(pNode->pWindowOwner)) { + pNode->lastSize = pNode->pSurface->exists() ? Vector2D{pNode->pSurface->wlr()->current.width, pNode->pSurface->wlr()->current.height} : Vector2D{}; + static auto* const PLOGDAMAGE = &g_pConfigManager->getConfigValuePtr("debug:log_damage")->intValue; if (*PLOGDAMAGE) Debug::log(LOG, "Refusing to commit damage from {} because it's invisible.", pNode->pWindowOwner); @@ -244,9 +246,13 @@ void Events::listener_commitSubsurface(void* owner, void* data) { } } - if (pNode->pSurface && pNode->pSurface->exists()) + if (pNode->pSurface && pNode->pSurface->exists()) { g_pHyprRenderer->damageSurface(pNode->pSurface->wlr(), lx, ly, SCALE); + if (pNode->lastSize != Vector2D{pNode->pSurface->wlr()->current.width, pNode->pSurface->wlr()->current.height} && pNode->pWindowOwner) + g_pHyprRenderer->damageWindow(pNode->pWindowOwner); + } + if (pNode->pWindowOwner) { if (pNode->pWindowOwner->m_bIsX11) pNode->pWindowOwner->m_vReportedSize = pNode->pWindowOwner->m_vPendingReportedSize; // apply pending size. We pinged, the window ponged. @@ -269,6 +275,8 @@ void Events::listener_commitSubsurface(void* owner, void* data) { } } } + + pNode->lastSize = pNode->pSurface->exists() ? Vector2D{pNode->pSurface->wlr()->current.width, pNode->pSurface->wlr()->current.height} : Vector2D{}; } void Events::listener_destroySubsurface(void* owner, void* data) { diff --git a/src/helpers/SubsurfaceTree.hpp b/src/helpers/SubsurfaceTree.hpp index d6f04a58..7a8b8fb8 100644 --- a/src/helpers/SubsurfaceTree.hpp +++ b/src/helpers/SubsurfaceTree.hpp @@ -26,6 +26,8 @@ struct SSurfaceTreeNode { void* globalOffsetData; CWindow* pWindowOwner = nullptr; + Vector2D lastSize; + // bool operator==(const SSurfaceTreeNode& rhs) const { return pSurface == rhs.pSurface; From 68935ba9dc85d87542174f761028cd426583cb26 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 12 Nov 2023 23:27:52 +0000 Subject: [PATCH 229/513] renderer: separate oversize uv calcs in dimensions --- src/render/Renderer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index ad3046e3..15ffc867 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -776,10 +776,10 @@ void CHyprRenderer::calculateUVForSurface(CWindow* pWindow, wlr_surface* pSurfac uvBR = uvBR - Vector2D(1.0 - WPERC * (uvBR.x - uvTL.x), 1.0 - HPERC * (uvBR.y - uvTL.y)); uvTL = uvTL + TOADDTL; - if (geom.width > pWindow->m_vRealSize.vec().x || geom.height > pWindow->m_vRealSize.vec().y) { + if (geom.width > pWindow->m_vRealSize.vec().x) uvBR.x = uvBR.x * (pWindow->m_vRealSize.vec().x / geom.width); + if (geom.height > pWindow->m_vRealSize.vec().y) uvBR.y = uvBR.y * (pWindow->m_vRealSize.vec().y / geom.height); - } } g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = uvTL; From 2e26542e3bba3533e71e13f2257823d96da2318a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 12 Nov 2023 23:57:53 +0000 Subject: [PATCH 230/513] renderer: use viewporter corrected size for uv calcs --- src/render/Renderer.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 15ffc867..1c698e5c 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -776,10 +776,16 @@ void CHyprRenderer::calculateUVForSurface(CWindow* pWindow, wlr_surface* pSurfac uvBR = uvBR - Vector2D(1.0 - WPERC * (uvBR.x - uvTL.x), 1.0 - HPERC * (uvBR.y - uvTL.y)); uvTL = uvTL + TOADDTL; - if (geom.width > pWindow->m_vRealSize.vec().x) - uvBR.x = uvBR.x * (pWindow->m_vRealSize.vec().x / geom.width); - if (geom.height > pWindow->m_vRealSize.vec().y) - uvBR.y = uvBR.y * (pWindow->m_vRealSize.vec().y / geom.height); + // TODO: make this passed to the func. Might break in the future. + auto maxSize = pWindow->m_vRealSize.vec(); + + if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall) + maxSize = pWindow->m_pWLSurface.getViewporterCorrectedSize(); + + if (geom.width > maxSize.x) + uvBR.x = uvBR.x * (maxSize.x / geom.width); + if (geom.height > maxSize.y) + uvBR.y = uvBR.y * (maxSize.y / geom.height); } g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = uvTL; From 016a7a9c9b1ca1f04a8d85c56699f6d6b77258a0 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 13 Nov 2023 16:30:37 +0000 Subject: [PATCH 231/513] hyprctl: use a rolling buffer for reading requests fixes #3846 --- src/debug/HyprCtl.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index c09251a8..217895b1 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1385,14 +1385,14 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) { if (mask & WL_EVENT_ERROR || mask & WL_EVENT_HANGUP) return 0; - sockaddr_in clientAddress; - socklen_t clientSize = sizeof(clientAddress); + sockaddr_in clientAddress; + socklen_t clientSize = sizeof(clientAddress); - const auto ACCEPTEDCONNECTION = accept4(HyprCtl::iSocketFD, (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC); + const auto ACCEPTEDCONNECTION = accept4(HyprCtl::iSocketFD, (sockaddr*)&clientAddress, &clientSize, SOCK_CLOEXEC); - char readBuffer[1024]; + std::array readBuffer; - fd_set fdset; + fd_set fdset; FD_ZERO(&fdset); FD_SET(ACCEPTEDCONNECTION, &fdset); timeval timeout = {.tv_sec = 0, .tv_usec = 5000}; @@ -1403,10 +1403,17 @@ int hyprCtlFDTick(int fd, uint32_t mask, void* data) { return 0; } - auto messageSize = read(ACCEPTEDCONNECTION, readBuffer, 1024); - readBuffer[messageSize == 1024 ? 1023 : messageSize] = '\0'; - - std::string request(readBuffer); + std::string request; + while (true) { + readBuffer.fill(0); + auto messageSize = read(ACCEPTEDCONNECTION, readBuffer.data(), 1023); + if (messageSize < 1) + break; + std::string recvd = readBuffer.data(); + request += recvd; + if (messageSize < 1023) + break; + } std::string reply = ""; From 4d6fa6ed0c6f10671c2bee337dc026f68cc12989 Mon Sep 17 00:00:00 2001 From: Ching Pei Yang <59727193+horriblename@users.noreply.github.com> Date: Mon, 13 Nov 2023 17:32:12 +0100 Subject: [PATCH 232/513] pluginapi: add touch event hooks (#3836) --- src/managers/input/Touch.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 24e299a7..965eee86 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -2,6 +2,8 @@ #include "../../Compositor.hpp" void CInputManager::onTouchDown(wlr_touch_down_event* e) { + EMIT_HOOK_EVENT_CANCELLABLE("touchDown", e); + auto PMONITOR = g_pCompositor->getMonitorFromName(e->touch->output_name ? e->touch->output_name : ""); const auto PDEVIT = std::find_if(m_lTouchDevices.begin(), m_lTouchDevices.end(), [&](const STouchDevice& other) { return other.pWlrDevice == &e->touch->base; }); @@ -52,12 +54,14 @@ void CInputManager::onTouchDown(wlr_touch_down_event* e) { } void CInputManager::onTouchUp(wlr_touch_up_event* e) { + EMIT_HOOK_EVENT_CANCELLABLE("touchUp", e); if (m_sTouchData.touchFocusSurface) { wlr_seat_touch_notify_up(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id); } } void CInputManager::onTouchMove(wlr_touch_motion_event* e) { + EMIT_HOOK_EVENT_CANCELLABLE("touchMove", e); if (m_sTouchData.touchFocusWindow && g_pCompositor->windowValidMapped(m_sTouchData.touchFocusWindow)) { const auto PMONITOR = g_pCompositor->getMonitorFromID(m_sTouchData.touchFocusWindow->m_iMonitorID); From 5edb4e4a304bbef1de30a36f7b921ea328d7efc6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 13 Nov 2023 16:42:45 +0000 Subject: [PATCH 233/513] decorations: recalc layout and positioner on add/remove --- src/Window.cpp | 4 ++++ src/render/decorations/DecorationPositioner.cpp | 10 ++++++++++ src/render/decorations/DecorationPositioner.hpp | 1 + 3 files changed, 15 insertions(+) diff --git a/src/Window.cpp b/src/Window.cpp index c1b79c2d..770350a4 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -202,12 +202,16 @@ void CWindow::updateWindowDecos() { void CWindow::addWindowDeco(std::unique_ptr deco) { m_dWindowDecorations.emplace_back(std::move(deco)); + g_pDecorationPositioner->forceRecalcFor(this); updateWindowDecos(); + g_pLayoutManager->getCurrentLayout()->recalculateWindow(this); } void CWindow::removeWindowDeco(IHyprWindowDecoration* deco) { m_vDecosToRemove.push_back(deco); + g_pDecorationPositioner->forceRecalcFor(this); updateWindowDecos(); + g_pLayoutManager->getCurrentLayout()->recalculateWindow(this); } pid_t CWindow::getPID() { diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index 937eaa9a..b41b92a9 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -95,6 +95,16 @@ void CDecorationPositioner::sanitizeDatas() { }); } +void CDecorationPositioner::forceRecalcFor(CWindow* pWindow) { + const auto WIT = std::find_if(m_mWindowDatas.begin(), m_mWindowDatas.end(), [&](const auto& other) { return other.first == pWindow; }); + if (WIT == m_mWindowDatas.end()) + return; + + const auto WINDOWDATA = &WIT->second; + + WINDOWDATA->needsRecalc = true; +} + void CDecorationPositioner::onWindowUpdate(CWindow* pWindow) { if (!g_pCompositor->windowExists(pWindow) || !pWindow->m_bIsMapped) return; diff --git a/src/render/decorations/DecorationPositioner.hpp b/src/render/decorations/DecorationPositioner.hpp index ae4a814a..740b4efe 100644 --- a/src/render/decorations/DecorationPositioner.hpp +++ b/src/render/decorations/DecorationPositioner.hpp @@ -71,6 +71,7 @@ class CDecorationPositioner { CBox getBoxWithIncludedDecos(CWindow* pWindow); void repositionDeco(IHyprWindowDecoration* deco); CBox getWindowDecorationBox(IHyprWindowDecoration* deco); + void forceRecalcFor(CWindow* pWindow); private: struct SWindowPositioningData { From 49597688e975c23b4f3bb53e77617ed3cd1e4937 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 14 Nov 2023 15:46:57 +0000 Subject: [PATCH 234/513] windowrules: make idleinhibit dynamic --- src/Window.cpp | 14 ++++++++++++++ src/events/Windows.cpp | 14 -------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Window.cpp b/src/Window.cpp index 770350a4..7569c869 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -591,6 +591,19 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { try { m_sAdditionalConfigData.xray = configStringToInt(vars[1]); } catch (...) {} + } 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); } } @@ -615,6 +628,7 @@ void CWindow::updateDynamicRules() { m_sAdditionalConfigData.xray = -1; m_sAdditionalConfigData.forceTearing = false; m_sAdditionalConfigData.nearestNeighbor = false; + m_eIdleInhibitMode = IDLEINHIBIT_NONE; const auto WINDOWRULES = g_pConfigManager->getMatchingRules(this); for (auto& r : WINDOWRULES) { diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 1d5384b7..39678154 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -246,20 +246,6 @@ void Events::listener_mapWindow(void* owner, void* data) { } vPrev = v; } - } else if (r.szRule.starts_with("idleinhibit")) { - auto IDLERULE = r.szRule.substr(r.szRule.find_first_of(' ') + 1); - - if (IDLERULE == "none") { - PWINDOW->m_eIdleInhibitMode = IDLEINHIBIT_NONE; - } else if (IDLERULE == "always") { - PWINDOW->m_eIdleInhibitMode = IDLEINHIBIT_ALWAYS; - } else if (IDLERULE == "focus") { - PWINDOW->m_eIdleInhibitMode = IDLEINHIBIT_FOCUS; - } else if (IDLERULE == "fullscreen") { - PWINDOW->m_eIdleInhibitMode = IDLEINHIBIT_FULLSCREEN; - } else { - Debug::log(ERR, "Rule idleinhibit: unknown mode {}", IDLERULE); - } } PWINDOW->applyDynamicRule(r); } From e8469f8b1bb184a08351ee3cc3fcc4d0638eb90b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 14 Nov 2023 19:51:47 +0000 Subject: [PATCH 235/513] renderer: drop unnecessary spammy logs --- src/render/Renderer.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 1c698e5c..6ea120ca 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1455,9 +1455,6 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vectorlayerSurface, box.width, box.height); - - Debug::log(LOG, "LayerSurface {:x} arranged: x: {} y: {} w: {} h: {} with margins: t: {} l: {} r: {} b: {}", (uintptr_t)&ls, box.x, box.y, box.width, box.height, - PSTATE->margin.top, PSTATE->margin.left, PSTATE->margin.right, PSTATE->margin.bottom); } } @@ -1496,8 +1493,6 @@ void CHyprRenderer::arrangeLayersForMonitor(const int& monitor) { damageMonitor(PMONITOR); g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitor); - - Debug::log(LOG, "Monitor {} layers arranged: reserved: {:5j} {:5j}", PMONITOR->szName, PMONITOR->vecReservedTopLeft, PMONITOR->vecReservedBottomRight); } void CHyprRenderer::damageSurface(wlr_surface* pSurface, double x, double y, double scale) { From e195e51c1bd4b17398ec6964f30751b6a54bbb44 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 14 Nov 2023 20:06:04 +0000 Subject: [PATCH 236/513] logging: move to an internal rolling log buffer disables logging to the logfile by default --- hyprctl/main.cpp | 2 ++ src/config/ConfigManager.cpp | 2 +- src/debug/CrashReporter.cpp | 2 +- src/debug/HyprCtl.cpp | 16 ++++++++++++++++ src/debug/HyprCtl.hpp | 3 ++- src/debug/Log.cpp | 17 ++++++++--------- src/debug/Log.hpp | 28 +++++++++++++++++----------- 7 files changed, 47 insertions(+), 23 deletions(-) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index c05b5201..deb8613c 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -396,6 +396,8 @@ int main(int argc, char** argv) { request(fullRequest); else if (fullRequest.contains("/globalshortcuts")) request(fullRequest); + else if (fullRequest.contains("/rollinglog")) + request(fullRequest); else if (fullRequest.contains("/instances")) instancesRequest(json); else if (fullRequest.contains("/switchxkblayout")) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 424b67a4..2bd1d91d 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -145,7 +145,7 @@ void CConfigManager::setDefaultVars() { configValues["debug:log_damage"].intValue = 0; configValues["debug:overlay"].intValue = 0; configValues["debug:damage_blink"].intValue = 0; - configValues["debug:disable_logs"].intValue = 0; + configValues["debug:disable_logs"].intValue = 1; configValues["debug:disable_time"].intValue = 1; configValues["debug:enable_stdout_logs"].intValue = 0; configValues["debug:damage_tracking"].intValue = DAMAGE_TRACKING_FULL; diff --git a/src/debug/CrashReporter.cpp b/src/debug/CrashReporter.cpp index ddc52561..14aa5c5b 100644 --- a/src/debug/CrashReporter.cpp +++ b/src/debug/CrashReporter.cpp @@ -119,7 +119,7 @@ void CrashReporter::createAndSaveCrash(int sig) { finalCrashReport += "\n\nLog tail:\n"; - finalCrashReport += execAndGet(("cat \"" + Debug::logFile + "\" | tail -n 50").c_str()); + finalCrashReport += Debug::rollingLog; const auto HOME = getenv("HOME"); const auto CACHE_HOME = getenv("XDG_CACHE_HOME"); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 217895b1..11f8d785 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -625,6 +625,20 @@ std::string animationsRequest(HyprCtl::eHyprCtlOutputFormat format) { return ret; } +std::string rollinglogRequest(HyprCtl::eHyprCtlOutputFormat format) { + std::string result = ""; + + if (format == HyprCtl::FORMAT_JSON) { + result += "[\n\"log\":\""; + result += escapeJSONStrings(Debug::rollingLog); + result += "\"]"; + } else { + result = Debug::rollingLog; + } + + return result; +} + std::string globalShortcutsRequest(HyprCtl::eHyprCtlOutputFormat format) { std::string ret = ""; const auto SHORTCUTS = g_pProtocolManager->m_pGlobalShortcutsProtocolManager->getAllShortcuts(); @@ -1351,6 +1365,8 @@ std::string getReply(std::string request) { return globalShortcutsRequest(format); else if (request == "animations") return animationsRequest(format); + else if (request == "rollinglog") + return rollinglogRequest(format); else if (request.starts_with("plugin")) return dispatchPlugin(request); else if (request.starts_with("notify")) diff --git a/src/debug/HyprCtl.hpp b/src/debug/HyprCtl.hpp index 00cf7c5b..4816c63c 100644 --- a/src/debug/HyprCtl.hpp +++ b/src/debug/HyprCtl.hpp @@ -19,7 +19,8 @@ namespace HyprCtl { inline int iSocketFD = -1; - enum eHyprCtlOutputFormat { + enum eHyprCtlOutputFormat + { FORMAT_NORMAL = 0, FORMAT_JSON }; diff --git a/src/debug/Log.cpp b/src/debug/Log.cpp index 98eeebc9..404904a2 100644 --- a/src/debug/Log.cpp +++ b/src/debug/Log.cpp @@ -10,25 +10,24 @@ void Debug::init(const std::string& IS) { } void Debug::wlrLog(wlr_log_importance level, const char* fmt, va_list args) { - if (disableLogs && *disableLogs) - return; - if (level > wlr_log_get_verbosity()) return; - char* outputStr = nullptr; - - std::ofstream ofs; - ofs.open(logFile, std::ios::out | std::ios::app); + char* outputStr = nullptr; vasprintf(&outputStr, fmt, args); std::string output = std::string(outputStr); free(outputStr); - ofs << "[wlr] " << output << "\n"; + rollingLog += output + "\n"; - ofs.close(); + if (!disableLogs || !*disableLogs) { + std::ofstream ofs; + ofs.open(logFile, std::ios::out | std::ios::app); + ofs << "[wlr] " << output << "\n"; + ofs.close(); + } if (!disableStdout) std::cout << output << "\n"; diff --git a/src/debug/Log.hpp b/src/debug/Log.hpp index 085465c9..659e2db4 100644 --- a/src/debug/Log.hpp +++ b/src/debug/Log.hpp @@ -7,9 +7,11 @@ #include "../includes.hpp" #include "../helpers/MiscFunctions.hpp" -#define LOGMESSAGESIZE 1024 +#define LOGMESSAGESIZE 1024 +#define ROLLING_LOG_SIZE 4096 -enum LogLevel { +enum LogLevel +{ NONE = -1, LOG = 0, WARN, @@ -26,12 +28,11 @@ namespace Debug { inline bool disableStdout = false; inline bool trace = false; + inline std::string rollingLog = ""; // rolling log contains the ROLLING_LOG_SIZE tail of the log + void init(const std::string& IS); template void log(LogLevel level, std::format_string fmt, Args&&... args) { - if (disableLogs && *disableLogs) - return; - if (level == TRACE && !trace) return; @@ -47,10 +48,6 @@ namespace Debug { default: break; } - // log to a file - std::ofstream ofs; - ofs.open(logFile, std::ios::out | std::ios::app); - // print date and time to the ofs if (disableTime && !*disableTime) { #ifndef _LIBCPP_VERSION @@ -69,9 +66,18 @@ namespace Debug { // 3. this is actually what std::format in stdlib does logMsg += std::vformat(fmt.get(), std::make_format_args(args...)); - ofs << logMsg << "\n"; + rollingLog += logMsg + "\n"; + if (rollingLog.size() > ROLLING_LOG_SIZE) + rollingLog = rollingLog.substr(rollingLog.size() - ROLLING_LOG_SIZE); - ofs.close(); + if (!disableLogs || !*disableLogs) { + // log to a file + std::ofstream ofs; + ofs.open(logFile, std::ios::out | std::ios::app); + ofs << logMsg << "\n"; + + ofs.close(); + } // log it to the stdout too. if (!disableStdout) From 81598b3dbdf3c01bb04fa377e65cfde91e6b2ab1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 14 Nov 2023 20:08:00 +0000 Subject: [PATCH 237/513] README: update showcase --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 10577c74..82dd0731 100644 --- a/README.md +++ b/README.md @@ -128,8 +128,8 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more... [Stars Preview]: https://starchart.cc/vaxerski/Hyprland.svg -[Preview A]: https://cdn.discordapp.com/attachments/1091569872535814185/1107675866101723277/screenshot-summer.png -[Preview B]: https://i.ibb.co/SX7GbYR/winter-rice.png +[Preview A]: https://i.ibb.co/C1yTb0r/falf.png +[Preview B]: https://cdn.discordapp.com/attachments/1091569872535814185/1107675866101723277/screenshot-summer.png [Preview C]: https://i.ibb.co/B3GJg28/20221126-20h53m26s-grim.png From 9e3dccca76ca3af4e96ac80c2ddef4774dc1354b Mon Sep 17 00:00:00 2001 From: thejch <66577496+thejch@users.noreply.github.com> Date: Wed, 15 Nov 2023 04:32:02 -0800 Subject: [PATCH 238/513] keybinds: Close special workspace after moving windows out of it (#3649) * use old monitor * use pMonitor for for special workspace --- src/managers/KeybindManager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 553872a5..aa35e3fd 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -949,6 +949,11 @@ void CKeybindManager::moveActiveToWorkspace(std::string args) { POLDWS->m_pLastFocusedWindow = g_pCompositor->getFirstWindowOnWorkspace(POLDWS->m_iID); + if (pWorkspace->m_bIsSpecialWorkspace) + pMonitor->setSpecialWorkspace(pWorkspace); + else if (POLDWS->m_bIsSpecialWorkspace) + g_pCompositor->getMonitorFromID(POLDWS->m_iMonitorID)->setSpecialWorkspace(nullptr); + pMonitor->changeWorkspace(pWorkspace); g_pCompositor->focusWindow(PWINDOW); From 91d6be1f09a0c0eaf585e88d315a7e56cac315a3 Mon Sep 17 00:00:00 2001 From: Dickby Date: Wed, 15 Nov 2023 21:32:44 +0100 Subject: [PATCH 239/513] groupbar: Fix position of groupbar titles on monitor scales != 1.0 (#3856) --- src/render/decorations/CHyprGroupBarDecoration.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 8f134c49..4e6776b4 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -118,8 +118,9 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& // render title if necessary if (*PRENDERTITLES) { - CBox rect = {ASSIGNEDBOX.x + xoff - pMonitor->vecPosition.x + offset.x, ASSIGNEDBOX.y - pMonitor->vecPosition.y + offset.y + BAR_PADDING_OUTER_VERT, m_fBarWidth, + CBox rect = {ASSIGNEDBOX.x + xoff - pMonitor->vecPosition.x + offset.x, ASSIGNEDBOX.y - pMonitor->vecPosition.y + offset.y + BAR_PADDING_OUTER_VERT, m_fBarWidth, ASSIGNEDBOX.h - BAR_INDICATOR_HEIGHT - BAR_PADDING_OUTER_VERT * 2}; + rect.scale(pMonitor->scale); CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[i]->m_szTitle); @@ -131,13 +132,10 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& refreshGradients(); - if (*PGRADIENTS) { - CBox rect2 = rect; - rect2.scale(pMonitor->scale); - g_pHyprOpenGL->renderTexture((m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? m_tGradientActive : m_tGradientInactive), &rect2, 1.0); - } + if (*PGRADIENTS) + g_pHyprOpenGL->renderTexture((m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? m_tGradientActive : m_tGradientInactive), &rect, 1.0); - rect.y = ASSIGNEDBOX.y + ASSIGNEDBOX.h / 2.0 - (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) / 2.0; + rect.y = (ASSIGNEDBOX.y + ASSIGNEDBOX.h / 2.0 - (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) / 2.0) * pMonitor->scale; rect.height = (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale; g_pHyprOpenGL->renderTexture(pTitleTex->tex, &rect, 1.f); @@ -414,4 +412,4 @@ CBox CHyprGroupBarDecoration::assignedBoxGlobal() { const auto WORKSPACEOFFSET = PWORKSPACE && !m_pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D(); return box.translate(WORKSPACEOFFSET); -} \ No newline at end of file +} From 28ef18a92112d57a425839a1993a1191af2fb6f3 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 16 Nov 2023 11:42:53 +0000 Subject: [PATCH 240/513] shadow: avoid using glClear and don't draw behind window if ignore_window fixes #3860 --- .../decorations/CHyprDropShadowDecoration.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index c992a4d8..7138dc20 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -126,12 +126,17 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D if (windowBox.width < 1 || windowBox.height < 1) return; // prevent assert failed + CRegion saveDamage = g_pHyprOpenGL->m_RenderData.damage; + + g_pHyprOpenGL->m_RenderData.damage = fullBox; + g_pHyprOpenGL->m_RenderData.damage.subtract(windowBox.expand(-ROUNDING * pMonitor->scale)).intersect(saveDamage); + alphaFB.bind(); // build the matte // 10-bit formats have dogshit alpha channels, so we have to use the matte to its fullest. - // first, clear with black (fully transparent) - g_pHyprOpenGL->clear(CColor(0, 0, 0, 1)); + // first, clear region of interest with black (fully transparent) + g_pHyprOpenGL->renderRect(&fullBox, CColor(0, 0, 0, 1), 0); // render white shadow with the alpha of the shadow color (otherwise we clear with alpha later and shit it to 2 bit) g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, CColor(1, 1, 1, m_pWindow->m_cRealShadowColor.col().a), a); @@ -142,7 +147,7 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D alphaSwapFB.bind(); // alpha swap just has the shadow color. It will be the "texture" to render. - g_pHyprOpenGL->clear(m_pWindow->m_cRealShadowColor.col().stripA()); + g_pHyprOpenGL->renderRect(&fullBox, m_pWindow->m_cRealShadowColor.col().stripA(), 0); LASTFB->bind(); @@ -150,6 +155,8 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D g_pHyprOpenGL->setMonitorTransformEnabled(false); g_pHyprOpenGL->renderTextureMatte(alphaSwapFB.m_cTex, &monbox, alphaFB); g_pHyprOpenGL->setMonitorTransformEnabled(true); + + g_pHyprOpenGL->m_RenderData.damage = saveDamage; } else { g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a); } From 859841f4d1ceb4060dcfcd2a94976805eaa39d62 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 16 Nov 2023 12:24:07 +0000 Subject: [PATCH 241/513] renderer: don't make snapshots of invisible windows on close --- src/render/OpenGL.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 826854ed..a7441a41 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1535,6 +1535,9 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) { if (!PMONITOR || !PMONITOR->output || PMONITOR->vecPixelSize.x <= 0 || PMONITOR->vecPixelSize.y <= 0) return; + if (!g_pHyprRenderer->shouldRenderWindow(pWindow)) + return; // ignore, window is not being rendered + wlr_output_attach_render(PMONITOR->output, nullptr); // we need to "damage" the entire monitor From 4868d4dfd3dca053915ddc3ec6444e7e96ebd8c6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 16 Nov 2023 17:31:52 +0000 Subject: [PATCH 242/513] shadow: avoid fatal mutation of the windowBox for calcs fixes #3865 --- src/helpers/Box.cpp | 4 ++++ src/helpers/Box.hpp | 2 ++ src/render/decorations/CHyprDropShadowDecoration.cpp | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/helpers/Box.cpp b/src/helpers/Box.cpp index 29aa81fa..3d57bc79 100644 --- a/src/helpers/Box.cpp +++ b/src/helpers/Box.cpp @@ -112,6 +112,10 @@ CBox CBox::roundInternal() { return CBox{std::floor(x), std::floor(y), std::floor(newW), std::floor(newH)}; } +CBox CBox::copy() const { + return CBox{*this}; +} + Vector2D CBox::pos() const { return {x, y}; } diff --git a/src/helpers/Box.hpp b/src/helpers/Box.hpp index cb07df06..5cb7f17f 100644 --- a/src/helpers/Box.hpp +++ b/src/helpers/Box.hpp @@ -52,6 +52,8 @@ class CBox { CBox& addExtents(const SWindowDecorationExtents& e); CBox& expand(const double& value); + CBox copy() const; + SWindowDecorationExtents extentsFrom(const CBox&); // this is the big box Vector2D middle() const; diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 7138dc20..d8972376 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -129,7 +129,7 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D CRegion saveDamage = g_pHyprOpenGL->m_RenderData.damage; g_pHyprOpenGL->m_RenderData.damage = fullBox; - g_pHyprOpenGL->m_RenderData.damage.subtract(windowBox.expand(-ROUNDING * pMonitor->scale)).intersect(saveDamage); + g_pHyprOpenGL->m_RenderData.damage.subtract(windowBox.copy().expand(-ROUNDING * pMonitor->scale)).intersect(saveDamage); alphaFB.bind(); From a34e192433d62e94692a90ea88f3ad384842d04e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 16 Nov 2023 20:20:41 +0000 Subject: [PATCH 243/513] renderer: clip floating boxes on slide anim fixes #3514 --- src/managers/AnimationManager.cpp | 6 ++++++ src/render/Renderer.cpp | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index e292de29..3d6ebdd8 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -213,6 +213,12 @@ void CAnimationManager::tick() { continue; w->updateWindowDecos(); + + if (w->m_bIsFloating) { + auto bb = w->getFullWindowBoundingBox(); + bb.translate(PWORKSPACE->m_vRenderOffset.vec()); + g_pHyprRenderer->damageBox(&bb); + } } } else if (PLAYER) { if (PLAYER->layer == ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND || PLAYER->layer == ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 6ea120ca..bf668004 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -419,6 +419,10 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* renderdata.y += offset.y; } + // if window is floating and we have a slide animation, clip it to its full bb + if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bIsFullscreen && PWORKSPACE->m_vRenderOffset.isBeingAnimated()) + g_pHyprOpenGL->m_RenderData.clipBox = pWindow->getFullWindowBoundingBox().translate(-pMonitor->vecPosition); + // render window decorations first, if not fullscreen full if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_MAIN) { @@ -508,6 +512,8 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* } } + g_pHyprOpenGL->m_RenderData.clipBox = CBox(); + if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_POPUP) { if (!pWindow->m_bIsX11) { CBox geom; @@ -540,7 +546,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* EMIT_HOOK_EVENT("render", RENDER_POST_WINDOW); g_pHyprOpenGL->m_pCurrentWindow = nullptr; - g_pHyprOpenGL->m_RenderData.clipBox = {0, 0, 0, 0}; + g_pHyprOpenGL->m_RenderData.clipBox = CBox(); } void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, timespec* time) { From 1d9bfa60a19975274afb5fd9a3492f8cb6742c2e Mon Sep 17 00:00:00 2001 From: Dickby Date: Thu, 16 Nov 2023 22:03:17 +0100 Subject: [PATCH 244/513] opengl: Don't use wrong shader just because it's GLES (#3867) --- src/render/OpenGL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index a7441a41..7cfe2c53 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -957,7 +957,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_TRUE, glMatrix); #else wlr_matrix_transpose(glMatrix, glMatrix); - glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURFINISH.proj, 1, GL_FALSE, glMatrix); + glUniformMatrix3fv(m_RenderData.pCurrentMonData->m_shBLURPREPARE.proj, 1, GL_FALSE, glMatrix); #endif glUniform1f(m_RenderData.pCurrentMonData->m_shBLURPREPARE.contrast, *PBLURCONTRAST); glUniform1f(m_RenderData.pCurrentMonData->m_shBLURPREPARE.brightness, *PBLURBRIGHTNESS); From 84bc0a73f6aad2bdbba9a36f7a751261abf606d9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 17 Nov 2023 15:29:51 +0000 Subject: [PATCH 245/513] compositor: drop unused vectorToWindow func --- src/Compositor.cpp | 40 ---------------------------------------- src/Compositor.hpp | 1 - 2 files changed, 41 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 70a19cb5..79e9360c 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -630,46 +630,6 @@ bool CCompositor::windowExists(CWindow* pWindow) { return false; } -CWindow* CCompositor::vectorToWindow(const Vector2D& pos) { - const auto PMONITOR = getMonitorFromVector(pos); - - if (PMONITOR->specialWorkspaceID) { - for (auto& w : m_vWindows | std::views::reverse) { - auto box = w->getWindowMainSurfaceBox(); - if (w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && box.containsPoint(pos) && !w->isHidden() && !w->m_bNoFocus) - return w.get(); - } - - for (auto& w : m_vWindows) { - auto box = w->getWindowMainSurfaceBox(); - if (w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && box.containsPoint(pos) && w->m_bIsMapped && !w->m_bIsFloating && !w->isHidden() && !w->m_bNoFocus) - return w.get(); - } - } - - // pinned - for (auto& w : m_vWindows | std::views::reverse) { - auto box = w->getWindowMainSurfaceBox(); - if (box.containsPoint(pos) && w->m_bIsMapped && w->m_bIsFloating && !w->isHidden() && w->m_bPinned && !w->m_bNoFocus) - return w.get(); - } - - // first loop over floating cuz they're above, m_vWindows should be sorted bottom->top, for tiled it doesn't matter. - for (auto& w : m_vWindows | std::views::reverse) { - auto box = w->getWindowMainSurfaceBox(); - if (box.containsPoint(pos) && w->m_bIsMapped && w->m_bIsFloating && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_bNoFocus) - return w.get(); - } - - for (auto& w : m_vWindows) { - auto box = w->getWindowMainSurfaceBox(); - if (box.containsPoint(pos) && w->m_bIsMapped && !w->m_bIsFloating && PMONITOR->activeWorkspace == w->m_iWorkspaceID && !w->isHidden() && !w->m_bNoFocus) - return w.get(); - } - - return nullptr; -} - CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) { const auto PMONITOR = getMonitorFromVector(pos); diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 59fc9136..7d187a80 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -137,7 +137,6 @@ class CCompositor { void focusSurface(wlr_surface*, CWindow* pWindowOwner = nullptr); bool windowExists(CWindow*); bool windowValidMapped(CWindow*); - CWindow* vectorToWindow(const Vector2D&); CWindow* vectorToWindowIdeal(const Vector2D&); // used only for finding a window to focus on, basically a "findFocusableWindow" CWindow* vectorToWindowTiled(const Vector2D&); wlr_surface* vectorToLayerSurface(const Vector2D&, std::vector>*, Vector2D*, SLayerSurface**); From 30ad71ff36739c06a57655b24fe197cca658062d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= Date: Fri, 17 Nov 2023 12:24:43 +0000 Subject: [PATCH 246/513] nix: add libGL to build inputs --- nix/default.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nix/default.nix b/nix/default.nix index a5ddd24c..63ef838e 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -10,6 +10,7 @@ git, hyprland-protocols, jq, + libGL, libdrm, libinput, libxcb, @@ -71,6 +72,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov git cairo hyprland-protocols + libGL libdrm libinput libxkbcommon From db8f13291a4e046e82c9b11c5bfd08f223bd52b1 Mon Sep 17 00:00:00 2001 From: TheAngusMcFire <43189215+TheAngusMcFire@users.noreply.github.com> Date: Fri, 17 Nov 2023 17:01:21 +0100 Subject: [PATCH 247/513] hyprctl: add monitors all to report all connected monitors (#3730) --------- Co-authored-by: Christian Rieger --- src/debug/HyprCtl.cpp | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 11f8d785..ea14768d 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -28,13 +28,22 @@ static std::string getWorkspaceNameFromSpecialID(const int workspaceID) { return workspace->m_szName; } -std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) { +std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat format) { + CVarList vars(request, 0, ' '); + auto allMonitors = false; + + if (vars.size() > 2) + return "too many args"; + + if (vars.size() == 2 && vars[1] == "all") + allMonitors = true; + std::string result = ""; if (format == HyprCtl::FORMAT_JSON) { result += "["; - for (auto& m : g_pCompositor->m_vMonitors) { - if (!m->output) + for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) { + if (!m->output || m->ID == -1ull) continue; result += std::format( @@ -68,7 +77,7 @@ std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) { }},)#", m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->output->description ? m->output->description : ""), (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, - (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace, escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName), + (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace, (m->activeWorkspace == -1 ? "" : escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName)), m->specialWorkspaceID, escapeJSONStrings(getWorkspaceNameFromSpecialID(m->specialWorkspaceID)), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "true" : "false"), (m->dpmsStatus ? "true" : "false"), (m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED ? "true" : "false"), @@ -79,8 +88,8 @@ std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) { result += "]"; } else { - for (auto& m : g_pCompositor->m_vMonitors) { - if (!m->output) + for (auto& m : allMonitors ? g_pCompositor->m_vRealMonitors : g_pCompositor->m_vMonitors) { + if (!m->output || m->ID == -1ull) continue; result += @@ -90,7 +99,7 @@ std::string monitorsRequest(HyprCtl::eHyprCtlOutputFormat format) { "{}\n\tfocused: {}\n\tdpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\n", m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, (m->output->description ? m->output->description : ""), (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), - (m->output->serial ? m->output->serial : ""), m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName, m->specialWorkspaceID, + (m->output->serial ? m->output->serial : ""), m->activeWorkspace, (m->activeWorkspace == -1 ? "" : g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName), m->specialWorkspaceID, getWorkspaceNameFromSpecialID(m->specialWorkspaceID), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, (int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED), m->tearingState.activelyTearing); @@ -1333,8 +1342,8 @@ std::string getReply(std::string request) { request = request.substr(sepIndex + 1); // remove flags and separator so we can compare the rest of the string } - if (request == "monitors") - return monitorsRequest(format); + if (request.starts_with("monitors")) + return monitorsRequest(request, format); else if (request == "workspaces") return workspacesRequest(format); else if (request == "workspacerules") From 51282f964f0bbf8e04fb3a62435a4e925b8945ed Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 17 Nov 2023 22:22:31 +0000 Subject: [PATCH 248/513] plugins: make logging on error more verbose ref #3874 --- src/debug/HyprCtl.cpp | 33 +++++++++++++++++---------------- src/plugins/PluginSystem.cpp | 9 ++++++++- src/plugins/PluginSystem.hpp | 1 + 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index ea14768d..1b1e53c3 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -30,8 +30,8 @@ static std::string getWorkspaceNameFromSpecialID(const int workspaceID) { std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat format) { CVarList vars(request, 0, ' '); - auto allMonitors = false; - + auto allMonitors = false; + if (vars.size() > 2) return "too many args"; @@ -77,8 +77,9 @@ std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat f }},)#", m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->output->description ? m->output->description : ""), (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, - (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace, (m->activeWorkspace == -1 ? "" : escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName)), - m->specialWorkspaceID, escapeJSONStrings(getWorkspaceNameFromSpecialID(m->specialWorkspaceID)), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, + (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace, + (m->activeWorkspace == -1 ? "" : escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName)), m->specialWorkspaceID, + escapeJSONStrings(getWorkspaceNameFromSpecialID(m->specialWorkspaceID)), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "true" : "false"), (m->dpmsStatus ? "true" : "false"), (m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED ? "true" : "false"), m->tearingState.activelyTearing ? "true" : "false"); @@ -92,17 +93,17 @@ std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat f if (!m->output || m->ID == -1ull) continue; - result += - std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\tspecial " - "workspace: {} ({})\n\treserved: {} " - "{} {} {}\n\tscale: {:.2f}\n\ttransform: " - "{}\n\tfocused: {}\n\tdpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\n", - m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, - (m->output->description ? m->output->description : ""), (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), - (m->output->serial ? m->output->serial : ""), m->activeWorkspace, (m->activeWorkspace == -1 ? "" : g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName), m->specialWorkspaceID, - getWorkspaceNameFromSpecialID(m->specialWorkspaceID), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, - (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, - (int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED), m->tearingState.activelyTearing); + result += std::format( + "Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\tspecial " + "workspace: {} ({})\n\treserved: {} " + "{} {} {}\n\tscale: {:.2f}\n\ttransform: " + "{}\n\tfocused: {}\n\tdpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\n", + m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, + (m->output->description ? m->output->description : ""), (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), + (m->output->serial ? m->output->serial : ""), m->activeWorkspace, (m->activeWorkspace == -1 ? "" : g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName), + m->specialWorkspaceID, getWorkspaceNameFromSpecialID(m->specialWorkspaceID), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, + (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"), + (int)m->dpmsStatus, (int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED), m->tearingState.activelyTearing); } } @@ -1253,7 +1254,7 @@ std::string dispatchPlugin(std::string request) { const auto PLUGIN = g_pPluginSystem->loadPlugin(PATH); if (!PLUGIN) - return "error in loading plugin"; + return "error in loading plugin, last error: " + g_pPluginSystem->m_szLastError; } else if (OPERATION == "unload") { if (vars.size() < 3) return "not enough args"; diff --git a/src/plugins/PluginSystem.cpp b/src/plugins/PluginSystem.cpp index a8ab904c..07dd226c 100644 --- a/src/plugins/PluginSystem.cpp +++ b/src/plugins/PluginSystem.cpp @@ -10,7 +10,10 @@ CPluginSystem::CPluginSystem() { CPlugin* CPluginSystem::loadPlugin(const std::string& path) { + m_szLastError = ""; + if (getPluginByPath(path)) { + m_szLastError = "Cannot load a plugin twice!"; Debug::log(ERR, " [PluginSystem] Cannot load a plugin twice!"); return nullptr; } @@ -22,6 +25,7 @@ CPlugin* CPluginSystem::loadPlugin(const std::string& path) { HANDLE MODULE = dlopen(path.c_str(), RTLD_LAZY); if (!MODULE) { + m_szLastError = std::format("Plugin {} could not be loaded: {}", path, dlerror()); Debug::log(ERR, " [PluginSystem] Plugin {} could not be loaded: {}", path, dlerror()); m_vLoadedPlugins.pop_back(); return nullptr; @@ -33,6 +37,7 @@ CPlugin* CPluginSystem::loadPlugin(const std::string& path) { PPLUGIN_INIT_FUNC initFunc = (PPLUGIN_INIT_FUNC)dlsym(MODULE, PLUGIN_INIT_FUNC_STR); if (!apiVerFunc || !initFunc) { + m_szLastError = std::format("Plugin {} could not be loaded: {}", path, "missing apiver/init func"); Debug::log(ERR, " [PluginSystem] Plugin {} could not be loaded. (No apiver/init func)", path); dlclose(MODULE); m_vLoadedPlugins.pop_back(); @@ -42,6 +47,7 @@ CPlugin* CPluginSystem::loadPlugin(const std::string& path) { const std::string PLUGINAPIVER = apiVerFunc(); if (PLUGINAPIVER != HYPRLAND_API_VERSION) { + m_szLastError = std::format("Plugin {} could not be loaded: {}", path, "API version mismatch"); Debug::log(ERR, " [PluginSystem] Plugin {} could not be loaded. (API version mismatch)", path); dlclose(MODULE); m_vLoadedPlugins.pop_back(); @@ -56,10 +62,11 @@ CPlugin* CPluginSystem::loadPlugin(const std::string& path) { PLUGINDATA = initFunc(MODULE); } else { // this module crashed. - throw std::exception(); + throw std::runtime_error("received a fatal signal"); } } catch (std::exception& e) { m_bAllowConfigVars = false; + m_szLastError = std::format("Plugin {} could not be loaded: plugin crashed/threw in main: {}", path, e.what()); Debug::log(ERR, " [PluginSystem] Plugin {} (Handle {:x}) crashed in init. Unloading.", path, (uintptr_t)MODULE); unloadPlugin(PLUGIN, true); // Plugin could've already hooked/done something return nullptr; diff --git a/src/plugins/PluginSystem.hpp b/src/plugins/PluginSystem.hpp index 0ef30bab..f0c9c9ad 100644 --- a/src/plugins/PluginSystem.hpp +++ b/src/plugins/PluginSystem.hpp @@ -38,6 +38,7 @@ class CPluginSystem { std::vector getAllPlugins(); bool m_bAllowConfigVars = false; + std::string m_szLastError = ""; private: std::vector> m_vLoadedPlugins; From 395985f81533417d74e1168ac7ea7a9a84c81d21 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 17 Nov 2023 22:24:52 +0000 Subject: [PATCH 249/513] pluginmgr: fix double use of dlerror() --- src/plugins/PluginSystem.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/PluginSystem.cpp b/src/plugins/PluginSystem.cpp index 07dd226c..1468cb79 100644 --- a/src/plugins/PluginSystem.cpp +++ b/src/plugins/PluginSystem.cpp @@ -25,8 +25,9 @@ CPlugin* CPluginSystem::loadPlugin(const std::string& path) { HANDLE MODULE = dlopen(path.c_str(), RTLD_LAZY); if (!MODULE) { - m_szLastError = std::format("Plugin {} could not be loaded: {}", path, dlerror()); - Debug::log(ERR, " [PluginSystem] Plugin {} could not be loaded: {}", path, dlerror()); + std::string strerr = dlerror(); + m_szLastError = std::format("Plugin {} could not be loaded: {}", path, strerr); + Debug::log(ERR, " [PluginSystem] Plugin {} could not be loaded: {}", path, strerr); m_vLoadedPlugins.pop_back(); return nullptr; } From a903dba8581aedfbc04b168e7074e22d1c3d004f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 17 Nov 2023 23:26:54 +0000 Subject: [PATCH 250/513] cmake: include tracy cpp if set --- CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dfe3c456..3bdbb0da 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,7 +106,13 @@ pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wa file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp") -add_executable(Hyprland ${SRCFILES}) +set(TRACY_CPP_FILES "") +if(USE_TRACY) + set(TRACY_CPP_FILES "subprojects/tracy/public/TracyClient.cpp") + message(STATUS "Tracy enabled, TRACY_CPP_FILES: " ${TRACY_CPP_FILES}) +endif() + +add_executable(Hyprland ${SRCFILES} ${TRACY_CPP_FILES}) add_dependencies(Hyprland wlroots) if(CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES DEBUG) From 483302a2cdc3cc8f4854aecb9cb0ed841babe30c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 17 Nov 2023 23:29:30 +0000 Subject: [PATCH 251/513] env: add HYPRLAND_NO_RT --- src/helpers/MiscFunctions.cpp | 4 ++++ src/main.cpp | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 85a81657..71263748 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -708,6 +708,10 @@ int64_t configStringToInt(const std::string& VALUE) { } else if (VALUE.starts_with("false") || VALUE.starts_with("off") || VALUE.starts_with("no")) { return 0; } + + if (VALUE.empty() || !isNumber(VALUE)) + return 0; + return std::stoll(VALUE); } diff --git a/src/main.cpp b/src/main.cpp index 40ddf390..27a768ba 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -97,7 +97,8 @@ int main(int argc, char** argv) { g_pCompositor->initServer(); - Init::gainRealTime(); + if (!getenv("HYPRLAND_NO_RT") || configStringToInt(std::string(getenv("HYPRLAND_NO_RT"))) == 0) + Init::gainRealTime(); Debug::log(LOG, "Hyprland init finished."); From 8b57a1973ea8b242783069e9a3e3d31e3cd939a8 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sat, 18 Nov 2023 17:00:24 +0000 Subject: [PATCH 252/513] internal: Allow floating windows on special (#3872) * allow floating on special * fix mistake * fix clipbox --- src/Compositor.cpp | 97 +++++++++++++++++---------------- src/managers/KeybindManager.cpp | 8 +-- src/render/Renderer.cpp | 35 +++--------- 3 files changed, 62 insertions(+), 78 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 79e9360c..0c6fbc60 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -657,24 +657,6 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { static auto* const PBORDERGRABEXTEND = &g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area")->intValue; const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0; - // special workspace - if (PMONITOR->specialWorkspaceID) { - for (auto& w : m_vWindows | std::views::reverse) { - const auto BB = w->getWindowInputBox(); - CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA}; - if (w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && box.containsPoint(pos) && !w->isHidden() && !w->m_bX11ShouldntFocus && - !w->m_bNoFocus) - return w.get(); - } - - for (auto& w : m_vWindows) { - CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; - if (!w->m_bIsFloating && w->m_iWorkspaceID == PMONITOR->specialWorkspaceID && w->m_bIsMapped && box.containsPoint(pos) && !w->isHidden() && !w->m_bX11ShouldntFocus && - !w->m_bNoFocus) - return w.get(); - } - } - // pinned windows on top of floating regardless for (auto& w : m_vWindows | std::views::reverse) { const auto BB = w->getWindowInputBox(); @@ -690,48 +672,69 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { } } - // first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter. - for (auto& w : m_vWindows | std::views::reverse) { - const auto BB = w->getWindowInputBox(); - CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA}; - if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_bNoFocus) { - // OR windows should add focus to parent - if (w->m_bX11ShouldntFocus && w->m_iX11Type != 2) + auto windowForWorkspace = [&](bool special) -> CWindow* { + // first loop over floating cuz they're above, m_lWindows should be sorted bottom->top, for tiled it doesn't matter. + for (auto& w : m_vWindows | std::views::reverse) { + + if (special && !isWorkspaceSpecial(w->m_iWorkspaceID)) // because special floating may creep up into regular continue; - if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y})) { + const auto BB = w->getWindowInputBox(); + CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA}; + if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_bNoFocus) { + // OR windows should add focus to parent + if (w->m_bX11ShouldntFocus && w->m_iX11Type != 2) + continue; - if (w->m_bIsX11 && w->m_iX11Type == 2 && !wlr_xwayland_or_surface_wants_focus(w->m_uSurface.xwayland)) { - // Override Redirect - return g_pCompositor->m_pLastWindow; // we kinda trick everything here. - // TODO: this is wrong, we should focus the parent, but idk how to get it considering it's nullptr in most cases. + if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y})) { + + if (w->m_bIsX11 && w->m_iX11Type == 2 && !wlr_xwayland_or_surface_wants_focus(w->m_uSurface.xwayland)) { + // Override Redirect + return g_pCompositor->m_pLastWindow; // we kinda trick everything here. + // TODO: this is wrong, we should focus the parent, but idk how to get it considering it's nullptr in most cases. + } + + return w.get(); } - return w.get(); + if (!w->m_bIsX11) { + if (w->hasPopupAt(pos)) + return w.get(); + } } + } - if (!w->m_bIsX11) { - if (w->hasPopupAt(pos)) + // for windows, we need to check their extensions too, first. + for (auto& w : m_vWindows) { + if (special != isWorkspaceSpecial(w->m_iWorkspaceID)) + continue; + + const int64_t WORKSPACEID = special ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace; + + if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_bNoFocus) { + if ((w)->hasPopupAt(pos)) return w.get(); } } - } + for (auto& w : m_vWindows) { + if (special != isWorkspaceSpecial(w->m_iWorkspaceID)) + continue; - // for windows, we need to check their extensions too, first. - for (auto& w : m_vWindows) { - if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_bNoFocus) { - if ((w)->hasPopupAt(pos)) + const int64_t WORKSPACEID = special ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace; + + CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; + if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_bNoFocus) return w.get(); } - } - for (auto& w : m_vWindows) { - CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; - if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == PMONITOR->activeWorkspace && !w->isHidden() && !w->m_bX11ShouldntFocus && - !w->m_bNoFocus) - return w.get(); - } - return nullptr; + return nullptr; + }; + + // special workspace + if (PMONITOR->specialWorkspaceID) + return windowForWorkspace(true); + + return windowForWorkspace(false); } CWindow* CCompositor::windowFromCursor() { @@ -2521,6 +2524,8 @@ CWorkspace* CCompositor::createNewWorkspace(const int& id, const int& monid, con PWORKSPACE->m_iID = id; PWORKSPACE->m_iMonitorID = monID; + PWORKSPACE->m_fAlpha.setValueAndWarp(0); + return PWORKSPACE; } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index aa35e3fd..c3a5efe1 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -735,11 +735,10 @@ void CKeybindManager::clearKeybinds() { void CKeybindManager::toggleActiveFloating(std::string args) { CWindow* PWINDOW = nullptr; - if (args != "" && args != "active" && args.length() > 1) { + if (args != "" && args != "active" && args.length() > 1) PWINDOW = g_pCompositor->getWindowByRegex(args); - } else { + else PWINDOW = g_pCompositor->m_pLastWindow; - } if (!PWINDOW) return; @@ -747,9 +746,6 @@ void CKeybindManager::toggleActiveFloating(std::string args) { // remove drag status g_pInputManager->currentlyDraggedWindow = nullptr; - if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID)) - return; - if (PWINDOW->m_sGroupData.pNextWindow && PWINDOW->m_sGroupData.pNextWindow != PWINDOW) { const auto PCURRENT = PWINDOW->getGroupCurrent(); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index bf668004..b78ddccd 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -253,9 +253,6 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork if (w->m_bIsFloating) continue; // floating are in the second pass - if (g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID)) - continue; // special are in the third pass - if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) continue; @@ -280,9 +277,6 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork if (w->m_bIsFloating) continue; // floating are in the second pass - if (g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID)) - continue; // special are in the third pass - if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) continue; @@ -298,9 +292,6 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork if (!w->m_bIsFloating || w->m_bPinned) continue; - if (g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID)) - continue; - if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) continue; @@ -316,9 +307,6 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork if (!w->m_bPinned || !w->m_bIsFloating) continue; - if (g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID)) - continue; - if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) continue; @@ -420,8 +408,11 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* } // if window is floating and we have a slide animation, clip it to its full bb - if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bIsFullscreen && PWORKSPACE->m_vRenderOffset.isBeingAnimated()) - g_pHyprOpenGL->m_RenderData.clipBox = pWindow->getFullWindowBoundingBox().translate(-pMonitor->vecPosition); + if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bIsFullscreen && PWORKSPACE->m_vRenderOffset.isBeingAnimated()) { + CRegion rg = pWindow->getFullWindowBoundingBox().translate(-pMonitor->vecPosition); + rg.add(CBox{0, 0, pMonitor->vecSize.x, pMonitor->vecSize.y}); + g_pHyprOpenGL->m_RenderData.clipBox = rg.getExtents(); + } // render window decorations first, if not fullscreen full if (mode == RENDER_PASS_ALL || mode == RENDER_PASS_MAIN) { @@ -681,18 +672,10 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* } } - for (auto& w : g_pCompositor->m_vWindows) { - if (w->isHidden() && !w->m_bIsMapped && !w->m_bFadingOut) - continue; - - if (!g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID)) - continue; - - if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) - continue; - - // render the bad boy - renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL); + // special + for (auto& ws : g_pCompositor->m_vWorkspaces) { + if (ws->m_iMonitorID == pMonitor->ID && ws->m_fAlpha.fl() > 0.f && ws->m_bIsSpecialWorkspace) + renderWorkspaceWindows(pMonitor, ws.get(), time); } EMIT_HOOK_EVENT("render", RENDER_POST_WINDOWS); From 89f6457a99c188454a4ebb429e80398668a13d28 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 18 Nov 2023 19:53:45 +0000 Subject: [PATCH 253/513] renderer: avoid rendering floating windows twice with special fixes #3887 --- src/render/Renderer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index b78ddccd..55cd0118 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -295,6 +295,9 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) continue; + if (pWorkspace->m_bIsSpecialWorkspace && w->m_iWorkspaceID != pWorkspace->m_iID) + continue; + // render the bad boy renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL); } From 6ad5f26cfebbdf48ed9633f2ba92e92f5b6622fb Mon Sep 17 00:00:00 2001 From: Dickby Date: Sat, 18 Nov 2023 20:59:12 +0100 Subject: [PATCH 254/513] layout: Don't update pseudoSize after window moved by mouse. (#3873) --- src/layout/IHyprLayout.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index abc1aeda..8bb51daf 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -427,7 +427,8 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) { const auto PSAVEDSIZE = pWindow->m_vRealSize.goalv(); // if the window is pseudo, update its size - pWindow->m_vPseudoSize = pWindow->m_vRealSize.goalv(); + if (!pWindow->m_bDraggingTiled) + pWindow->m_vPseudoSize = pWindow->m_vRealSize.goalv(); pWindow->m_vLastFloatingSize = PSAVEDSIZE; From 3d89654254a3cc23a57e1bdcd39ad9f743bf98e2 Mon Sep 17 00:00:00 2001 From: Dickby Date: Sat, 18 Nov 2023 22:37:16 +0100 Subject: [PATCH 255/513] vector: New operator overloads and small fix in Vector2D. (#3891) --- src/helpers/Vector2D.hpp | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/helpers/Vector2D.hpp b/src/helpers/Vector2D.hpp index c79c967c..34b06862 100644 --- a/src/helpers/Vector2D.hpp +++ b/src/helpers/Vector2D.hpp @@ -25,10 +25,10 @@ class Vector2D { Vector2D operator-() const { return Vector2D(-this->x, -this->y); } - Vector2D operator*(const float& a) const { + Vector2D operator*(const double& a) const { return Vector2D(this->x * a, this->y * a); } - Vector2D operator/(const float& a) const { + Vector2D operator/(const double& a) const { return Vector2D(this->x / a, this->y / a); } @@ -55,6 +55,36 @@ class Vector2D { bool operator<(const Vector2D& a) const { return this->x < a.x && this->y < a.y; } + Vector2D& operator+=(const Vector2D& a) { + this->x += a.x; + this->y += a.y; + return *this; + } + Vector2D& operator-=(const Vector2D& a) { + this->x -= a.x; + this->y -= a.y; + return *this; + } + Vector2D& operator*=(const Vector2D& a) { + this->x *= a.x; + this->y *= a.y; + return *this; + } + Vector2D& operator/=(const Vector2D& a) { + this->x /= a.x; + this->y /= a.y; + return *this; + } + Vector2D& operator*=(const double& a) { + this->x *= a; + this->y *= a; + return *this; + } + Vector2D& operator/=(const double& a) { + this->x /= a; + this->y /= a; + return *this; + } double distance(const Vector2D& other) const; double size() const; From add23a9ba26c6363c7180ed0b23394d9f1328be2 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Sun, 19 Nov 2023 12:29:01 +0000 Subject: [PATCH 256/513] group: fix dragging into floating groups (#3719) * allow dragging into floating groups modified: src/Compositor.cpp modified: src/Compositor.hpp modified: src/layout/IHyprLayout.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * floating-only modified: src/layout/IHyprLayout.cpp --- src/Compositor.cpp | 12 ++++---- src/Compositor.hpp | 5 ++-- src/layout/IHyprLayout.cpp | 29 ++++++++++++++++++- .../decorations/CHyprGroupBarDecoration.cpp | 3 ++ 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 0c6fbc60..1b27a0f4 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -650,7 +650,7 @@ CWindow* CCompositor::vectorToWindowTiled(const Vector2D& pos) { return nullptr; } -CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { +CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos, CWindow* pIgnoreWindow) { const auto PMONITOR = getMonitorFromVector(pos); static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue; static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; @@ -661,7 +661,7 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { for (auto& w : m_vWindows | std::views::reverse) { const auto BB = w->getWindowInputBox(); CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA}; - if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_bNoFocus) { + if (w->m_bIsFloating && w->m_bIsMapped && !w->isHidden() && !w->m_bX11ShouldntFocus && w->m_bPinned && !w->m_bNoFocus && w.get() != pIgnoreWindow) { if (box.containsPoint({m_sWLRCursor->x, m_sWLRCursor->y})) return w.get(); @@ -681,7 +681,7 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { const auto BB = w->getWindowInputBox(); CBox box = {BB.x - BORDER_GRAB_AREA, BB.y - BORDER_GRAB_AREA, BB.width + 2 * BORDER_GRAB_AREA, BB.height + 2 * BORDER_GRAB_AREA}; - if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_bNoFocus) { + if (w->m_bIsFloating && w->m_bIsMapped && isWorkspaceVisible(w->m_iWorkspaceID) && !w->isHidden() && !w->m_bPinned && !w->m_bNoFocus && w.get() != pIgnoreWindow) { // OR windows should add focus to parent if (w->m_bX11ShouldntFocus && w->m_iX11Type != 2) continue; @@ -711,7 +711,8 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { const int64_t WORKSPACEID = special ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace; - if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_bNoFocus) { + if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_bNoFocus && + w.get() != pIgnoreWindow) { if ((w)->hasPopupAt(pos)) return w.get(); } @@ -723,7 +724,8 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos) { const int64_t WORKSPACEID = special ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace; CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; - if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_bNoFocus) + if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_bNoFocus && + w.get() != pIgnoreWindow) return w.get(); } diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 7d187a80..829b7e79 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -29,8 +29,7 @@ #include "plugins/PluginSystem.hpp" #include "helpers/Watchdog.hpp" -enum eManagersInitStage -{ +enum eManagersInitStage { STAGE_PRIORITY = 0, STAGE_LATE }; @@ -137,7 +136,7 @@ class CCompositor { void focusSurface(wlr_surface*, CWindow* pWindowOwner = nullptr); bool windowExists(CWindow*); bool windowValidMapped(CWindow*); - CWindow* vectorToWindowIdeal(const Vector2D&); // used only for finding a window to focus on, basically a "findFocusableWindow" + CWindow* vectorToWindowIdeal(const Vector2D&, CWindow* pIgnoreWindow = nullptr); // used only for finding a window to focus on, basically a "findFocusableWindow" CWindow* vectorToWindowTiled(const Vector2D&); wlr_surface* vectorToLayerSurface(const Vector2D&, std::vector>*, Vector2D*, SLayerSurface**); wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 8bb51daf..acd84684 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -1,6 +1,7 @@ #include "IHyprLayout.hpp" #include "../defines.hpp" #include "../Compositor.hpp" +#include "../render/decorations/CHyprGroupBarDecoration.hpp" void IHyprLayout::onWindowCreated(CWindow* pWindow, eDirection direction) { if (pWindow->m_bIsFloating) { @@ -264,10 +265,36 @@ void IHyprLayout::onEndDragWindow() { g_pInputManager->refocus(); changeWindowFloatingMode(DRAGGINGWINDOW); DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; + } else if (g_pInputManager->dragMode == MBIND_MOVE) { + g_pHyprRenderer->damageWindow(DRAGGINGWINDOW); + const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); + CWindow* pWindow = g_pCompositor->vectorToWindowIdeal(MOUSECOORDS, DRAGGINGWINDOW); + + if (pWindow && pWindow->m_bIsFloating) { + for (auto& wd : pWindow->m_dWindowDecorations) { + if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) + continue; + + if (g_pDecorationPositioner->getWindowDecorationBox(wd.get()).containsPoint(MOUSECOORDS)) { + if (!wd->onEndWindowDragOnDeco(DRAGGINGWINDOW, MOUSECOORDS)) + return; + break; + } + } + + if (pWindow->m_sGroupData.pNextWindow && DRAGGINGWINDOW->canBeGroupedInto(pWindow)) { + static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue; + (*USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW); + pWindow->setGroupCurrent(DRAGGINGWINDOW); + DRAGGINGWINDOW->updateWindowDecos(); + + if (!DRAGGINGWINDOW->getDecorationByType(DECORATION_GROUPBAR)) + DRAGGINGWINDOW->addWindowDeco(std::make_unique(DRAGGINGWINDOW)); + } + } } g_pHyprRenderer->damageWindow(DRAGGINGWINDOW); - g_pCompositor->focusWindow(DRAGGINGWINDOW); g_pInputManager->m_bWasDraggingWindow = false; diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 4e6776b4..acf74cef 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -344,6 +344,9 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(CWindow* pDraggedWindow, con pDraggedWindow->updateWindowDecos(); g_pLayoutManager->getCurrentLayout()->recalculateWindow(pDraggedWindow); + if (!pDraggedWindow->getDecorationByType(DECORATION_GROUPBAR)) + pDraggedWindow->addWindowDeco(std::make_unique(pDraggedWindow)); + return false; } From 7e0c90b92c1229b3c453d2fbd1609affa9631ce2 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Sun, 19 Nov 2023 12:29:26 +0000 Subject: [PATCH 257/513] groupbar: fix text pos with verical offset (#3893) modified: src/render/decorations/CHyprGroupBarDecoration.cpp --- src/render/decorations/CHyprGroupBarDecoration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index acf74cef..7d2c84ee 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -135,7 +135,7 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& if (*PGRADIENTS) g_pHyprOpenGL->renderTexture((m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? m_tGradientActive : m_tGradientInactive), &rect, 1.0); - rect.y = (ASSIGNEDBOX.y + ASSIGNEDBOX.h / 2.0 - (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) / 2.0) * pMonitor->scale; + rect.y += (ASSIGNEDBOX.h / 2.0 - (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) / 2.0) * pMonitor->scale; rect.height = (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale; g_pHyprOpenGL->renderTexture(pTitleTex->tex, &rect, 1.f); From 646f4bc63861e03b01fed3833bb65d1d014e1bf3 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Sun, 19 Nov 2023 19:33:26 +0700 Subject: [PATCH 258/513] general: add workspace gaps (#3877) * anims: workspace gap * anims: ws gaps: on swipe end * anims: ws gaps: add missing parentheses * format * refractor * Update Swipe.cpp * format * fix swipe to right * ws gaps: move animations:workspace_gap to general:gaps_workspace * ws gaps: general:gaps_workspace -> general:gaps_workspaces --- src/config/ConfigManager.cpp | 1 + src/helpers/Workspace.cpp | 13 +++--- src/managers/input/Swipe.cpp | 85 +++++++++++++++++++++--------------- 3 files changed, 59 insertions(+), 40 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 2bd1d91d..9f739ce0 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -79,6 +79,7 @@ void CConfigManager::setDefaultVars() { configValues["general:no_border_on_floating"].intValue = 0; configValues["general:gaps_in"].intValue = 5; configValues["general:gaps_out"].intValue = 20; + configValues["general:gaps_workspaces"].intValue = 0; ((CGradientValueData*)configValues["general:col.active_border"].data.get())->reset(0xffffffff); ((CGradientValueData*)configValues["general:col.inactive_border"].data.get())->reset(0xff444444); ((CGradientValueData*)configValues["general:col.nogroup_border"].data.get())->reset(0xff444444); diff --git a/src/helpers/Workspace.cpp b/src/helpers/Workspace.cpp index 3264b27f..c027688e 100644 --- a/src/helpers/Workspace.cpp +++ b/src/helpers/Workspace.cpp @@ -38,7 +38,8 @@ CWorkspace::~CWorkspace() { } void CWorkspace::startAnim(bool in, bool left, bool instant) { - const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle; + const auto ANIMSTYLE = m_fAlpha.m_pConfig->pValues->internalStyle; + const auto PWORKSPACEGAP = &g_pConfigManager->getConfigValuePtr("general:gaps_workspaces")->intValue; if (ANIMSTYLE.starts_with("slidefade")) { const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); @@ -90,26 +91,28 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { } 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 ? PMONITOR->vecSize.y : -PMONITOR->vecSize.y)); + m_vRenderOffset.setValueAndWarp(Vector2D(0, left ? YDISTANCE : -YDISTANCE)); m_vRenderOffset = Vector2D(0, 0); } else { - m_vRenderOffset = Vector2D(0, left ? -PMONITOR->vecSize.y : PMONITOR->vecSize.y); + 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 ? PMONITOR->vecSize.x : -PMONITOR->vecSize.x, 0)); + m_vRenderOffset.setValueAndWarp(Vector2D(left ? XDISTANCE : -XDISTANCE, 0)); m_vRenderOffset = Vector2D(0, 0); } else { - m_vRenderOffset = Vector2D(left ? -PMONITOR->vecSize.x : PMONITOR->vecSize.x, 0); + m_vRenderOffset = Vector2D(left ? -XDISTANCE : XDISTANCE, 0); } } diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index dba3d735..d093b8c3 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -44,13 +44,14 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) { if (!m_sActiveSwipe.pWorkspaceBegin) return; // no valid swipe - static auto* const PSWIPEPERC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_cancel_ratio")->floatValue; - static auto* const PSWIPEDIST = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_distance")->intValue; - static auto* const PSWIPEFORC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_min_speed_to_force")->intValue; - static auto* const PSWIPENEW = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_create_new")->intValue; - static auto* const PSWIPENUMBER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_numbered")->intValue; - static auto* const PSWIPEUSER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_use_r")->intValue; - const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || + static auto* const PSWIPEPERC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_cancel_ratio")->floatValue; + static auto* const PSWIPEDIST = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_distance")->intValue; + static auto* const PSWIPEFORC = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_min_speed_to_force")->intValue; + static auto* const PSWIPENEW = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_create_new")->intValue; + static auto* const PSWIPENUMBER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_numbered")->intValue; + static auto* const PSWIPEUSER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_use_r")->intValue; + static auto* const PWORKSPACEGAP = &g_pConfigManager->getConfigValuePtr("general:gaps_workspaces")->intValue; + const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); // commit @@ -75,10 +76,12 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) { workspaceIDRight = maxWorkspace + 1; } - auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); // not guaranteed if PSWIPENEW || PSWIPENUMBER - auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); // not guaranteed if PSWIPENUMBER + auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); // not guaranteed if PSWIPENEW || PSWIPENUMBER + auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); // not guaranteed if PSWIPENUMBER - const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.vec(); + const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.vec(); + const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + *PWORKSPACEGAP; + const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + *PWORKSPACEGAP; CWorkspace* pSwitchedTo = nullptr; @@ -94,18 +97,19 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) { } else { if (m_sActiveSwipe.delta < 0) { // to left + if (PWORKSPACEL) { if (VERTANIMS) - PWORKSPACEL->m_vRenderOffset = Vector2D({0, -m_sActiveSwipe.pMonitor->vecSize.y}); + PWORKSPACEL->m_vRenderOffset = Vector2D({0, -YDISTANCE}); else - PWORKSPACEL->m_vRenderOffset = Vector2D({-m_sActiveSwipe.pMonitor->vecSize.x, 0}); + PWORKSPACEL->m_vRenderOffset = Vector2D({-XDISTANCE, 0}); } } else if (PWORKSPACER) { // to right if (VERTANIMS) - PWORKSPACER->m_vRenderOffset = Vector2D({0, m_sActiveSwipe.pMonitor->vecSize.y}); + PWORKSPACER->m_vRenderOffset = Vector2D({0, YDISTANCE}); else - PWORKSPACER->m_vRenderOffset = Vector2D({m_sActiveSwipe.pMonitor->vecSize.x, 0}); + PWORKSPACER->m_vRenderOffset = Vector2D({XDISTANCE, 0}); } m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(); @@ -128,9 +132,9 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) { m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0, m_sActiveSwipe.pMonitor->vecSize.y); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0, YDISTANCE); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(m_sActiveSwipe.pMonitor->vecSize.x, 0); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(XDISTANCE, 0); m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(1.f); g_pInputManager->unconstrainMouse(); @@ -154,9 +158,9 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) { m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValue(RENDEROFFSETMIDDLE); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0, -m_sActiveSwipe.pMonitor->vecSize.y); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(0, -YDISTANCE); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(-m_sActiveSwipe.pMonitor->vecSize.x, 0); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset = Vector2D(-XDISTANCE, 0); m_sActiveSwipe.pWorkspaceBegin->m_fAlpha.setValueAndWarp(1.f); g_pInputManager->unconstrainMouse(); @@ -198,8 +202,11 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { static auto* const PSWIPEFOREVER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_forever")->intValue; static auto* const PSWIPENUMBER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_numbered")->intValue; static auto* const PSWIPEUSER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_use_r")->intValue; + static auto* const PWORKSPACEGAP = &g_pConfigManager->getConfigValuePtr("general:gaps_workspaces")->intValue; - const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || + const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + *PWORKSPACEGAP; + const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + *PWORKSPACEGAP; + const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); m_sActiveSwipe.delta += VERTANIMS ? (*PSWIPEINVR ? -e->dy : e->dy) : (*PSWIPEINVR ? -e->dx : e->dx); @@ -244,9 +251,11 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.y)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp( + Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE)); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp( + Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0)); g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); return; @@ -268,13 +277,15 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { } if (VERTANIMS) { - PWORKSPACE->m_vRenderOffset.setValueAndWarp( - Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.y - m_sActiveSwipe.pMonitor->vecSize.y)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.y)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D( + 0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE - YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp( + Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE)); } else { - PWORKSPACE->m_vRenderOffset.setValueAndWarp( - Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x - m_sActiveSwipe.pMonitor->vecSize.x, 0)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D( + ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE - XDISTANCE, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp( + Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0)); } g_pCompositor->updateWorkspaceWindowDecos(workspaceIDLeft); @@ -286,9 +297,11 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.y)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp( + Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE)); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp( + Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0)); g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); return; @@ -310,13 +323,15 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { } if (VERTANIMS) { - PWORKSPACE->m_vRenderOffset.setValueAndWarp( - Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.y + m_sActiveSwipe.pMonitor->vecSize.y)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.y)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D( + 0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE + YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp( + Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE)); } else { - PWORKSPACE->m_vRenderOffset.setValueAndWarp( - Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x + m_sActiveSwipe.pMonitor->vecSize.x, 0)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * m_sActiveSwipe.pMonitor->vecSize.x, 0)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D( + ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE + XDISTANCE, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp( + Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0)); } g_pCompositor->updateWorkspaceWindowDecos(workspaceIDRight); From 6d26199e1ccd2f99084ec5a9107b8e7cdd286249 Mon Sep 17 00:00:00 2001 From: thejch <66577496+thejch@users.noreply.github.com> Date: Mon, 20 Nov 2023 04:13:09 -0800 Subject: [PATCH 259/513] renderer: fix floating window rendering when scale > 1 (#3901) --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 55cd0118..fb8e6aab 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -412,7 +412,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* // if window is floating and we have a slide animation, clip it to its full bb if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bIsFullscreen && PWORKSPACE->m_vRenderOffset.isBeingAnimated()) { - CRegion rg = pWindow->getFullWindowBoundingBox().translate(-pMonitor->vecPosition); + CRegion rg = pWindow->getFullWindowBoundingBox().translate(-pMonitor->vecPosition).scale(pMonitor->scale); rg.add(CBox{0, 0, pMonitor->vecSize.x, pMonitor->vecSize.y}); g_pHyprOpenGL->m_RenderData.clipBox = rg.getExtents(); } From 7d1c8d827a1f17200fe868983b203c15cc91d0df Mon Sep 17 00:00:00 2001 From: thejch <66577496+thejch@users.noreply.github.com> Date: Mon, 20 Nov 2023 14:34:28 -0800 Subject: [PATCH 260/513] shadow: add workspace offset to floating window shadow (#3906) --- src/render/decorations/CHyprDropShadowDecoration.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index d8972376..bbf6def4 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -92,6 +92,7 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D // scale the box in relation to the center of the box fullBox.scaleFromCenter(SHADOWSCALE).translate(*PSHADOWOFFSET); + m_vLastWindowPos += WORKSPACEOFFSET; m_seExtents = {{m_vLastWindowPos.x - fullBox.x - pMonitor->vecPosition.x + 2, m_vLastWindowPos.y - fullBox.y - pMonitor->vecPosition.y + 2}, {fullBox.x + fullBox.width + pMonitor->vecPosition.x - m_vLastWindowPos.x - m_vLastWindowSize.x + 2, fullBox.y + fullBox.height + pMonitor->vecPosition.y - m_vLastWindowPos.y - m_vLastWindowSize.y + 2}}; From 572fd554b8e86b3b3533f05631348c3374815ab5 Mon Sep 17 00:00:00 2001 From: thejch <66577496+thejch@users.noreply.github.com> Date: Mon, 20 Nov 2023 16:34:34 -0800 Subject: [PATCH 261/513] renderer: Fix floating clipbox (#3907) * fix floating decoration clipbox scale * use vecTransformedSize * use workspace offset --- src/render/Renderer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index fb8e6aab..cd710137 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -412,8 +412,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* // if window is floating and we have a slide animation, clip it to its full bb if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bIsFullscreen && PWORKSPACE->m_vRenderOffset.isBeingAnimated()) { - CRegion rg = pWindow->getFullWindowBoundingBox().translate(-pMonitor->vecPosition).scale(pMonitor->scale); - rg.add(CBox{0, 0, pMonitor->vecSize.x, pMonitor->vecSize.y}); + CRegion rg = pWindow->getFullWindowBoundingBox().translate(-pMonitor->vecPosition + PWORKSPACE->m_vRenderOffset.vec()).scale(pMonitor->scale); g_pHyprOpenGL->m_RenderData.clipBox = rg.getExtents(); } From 472926528428cd714c90f157e639fc0466611c8b Mon Sep 17 00:00:00 2001 From: zakk4223 Date: Tue, 21 Nov 2023 13:43:38 -0500 Subject: [PATCH 262/513] hyprctl: Add 'layouts' command (#3895) * Add hyprctl 'layouts' command formatting * Add getAllLayoutNames(), move m_vLayouts back to private Formatting * clang-format --- hyprctl/main.cpp | 3 +++ src/debug/HyprCtl.cpp | 28 ++++++++++++++++++++++++++-- src/managers/LayoutManager.cpp | 7 +++++++ src/managers/LayoutManager.hpp | 15 +++++++-------- 4 files changed, 43 insertions(+), 10 deletions(-) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index deb8613c..74127d5b 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -52,6 +52,7 @@ commands: notify globalshortcuts instances + layouts flags: -j -> output in JSON @@ -420,6 +421,8 @@ int main(int argc, char** argv) { request(fullRequest, 2); else if (fullRequest.contains("/hyprpaper")) requestHyprpaper(fullRequest); + else if (fullRequest.contains("/layouts")) + request(fullRequest); else if (fullRequest.contains("/--help")) printf("%s", USAGE.c_str()); else { diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 1b1e53c3..9745a0fe 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -260,7 +260,7 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, HyprCtl::eHyprC std::string result = std::format(R"#({{ "workspaceString": "{}"{}{}{}{}{}{}{}{} }})#", - escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, borderSize, border, rounding, decorate, shadow); + escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, borderSize, border, rounding, decorate, shadow); return result; } else { @@ -276,7 +276,7 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, HyprCtl::eHyprC const std::string shadow = std::format("\tshadow: {}\n", (bool)(r.shadow) ? boolToString(r.shadow.value()) : ""); std::string result = std::format("Workspace rule {}:\n{}{}{}{}{}{}{}{}{}{}\n", escapeJSONStrings(r.workspaceString), monitor, default_, persistent, gapsIn, gapsOut, - borderSize, border, rounding, decorate, shadow); + borderSize, border, rounding, decorate, shadow); return result; } @@ -423,6 +423,28 @@ std::string layersRequest(HyprCtl::eHyprCtlOutputFormat format) { return result; } +std::string layoutsRequest(HyprCtl::eHyprCtlOutputFormat format) { + std::string result = ""; + if (format == HyprCtl::FORMAT_JSON) { + result += "["; + + for (auto& m : g_pLayoutManager->getAllLayoutNames()) { + result += std::format( + R"#( + "{}",)#", + m); + } + trimTrailingComma(result); + + result += "\n]\n"; + } else { + for (auto& m : g_pLayoutManager->getAllLayoutNames()) { + result += std::format("{}\n", m); + } + } + return result; +} + std::string devicesRequest(HyprCtl::eHyprCtlOutputFormat format) { std::string result = ""; @@ -1377,6 +1399,8 @@ std::string getReply(std::string request) { return animationsRequest(format); else if (request == "rollinglog") return rollinglogRequest(format); + else if (request == "layouts") + return layoutsRequest(format); else if (request.starts_with("plugin")) return dispatchPlugin(request); else if (request.starts_with("notify")) diff --git a/src/managers/LayoutManager.cpp b/src/managers/LayoutManager.cpp index bf4ca8bd..70c2d2a3 100644 --- a/src/managers/LayoutManager.cpp +++ b/src/managers/LayoutManager.cpp @@ -51,3 +51,10 @@ bool CLayoutManager::removeLayout(IHyprLayout* layout) { return true; } + +std::vector CLayoutManager::getAllLayoutNames() { + std::vector results(m_vLayouts.size()); + for (size_t i = 0; i < m_vLayouts.size(); ++i) + results[i] = m_vLayouts[i].first; + return results; +} diff --git a/src/managers/LayoutManager.hpp b/src/managers/LayoutManager.hpp index 1ebe5711..78d86797 100644 --- a/src/managers/LayoutManager.hpp +++ b/src/managers/LayoutManager.hpp @@ -7,16 +7,16 @@ class CLayoutManager { public: CLayoutManager(); - IHyprLayout* getCurrentLayout(); + IHyprLayout* getCurrentLayout(); - void switchToLayout(std::string); + void switchToLayout(std::string); - bool addLayout(const std::string& name, IHyprLayout* layout); - bool removeLayout(IHyprLayout* layout); + bool addLayout(const std::string& name, IHyprLayout* layout); + bool removeLayout(IHyprLayout* layout); + std::vector getAllLayoutNames(); private: - enum HYPRLAYOUTS - { + enum HYPRLAYOUTS { LAYOUT_DWINDLE = 0, LAYOUT_MASTER }; @@ -25,8 +25,7 @@ class CLayoutManager { CHyprDwindleLayout m_cDwindleLayout; CHyprMasterLayout m_cMasterLayout; - std::vector> m_vLayouts; }; -inline std::unique_ptr g_pLayoutManager; \ No newline at end of file +inline std::unique_ptr g_pLayoutManager; From d417370bb725eb58f385b0cbfc924090462164f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ng=C3=B4=20Huy?= Date: Wed, 22 Nov 2023 18:02:36 +0700 Subject: [PATCH 263/513] makefile: Add CXXFLAGS to hyprlctl's Makefile (#3913) --- hyprctl/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hyprctl/Makefile b/hyprctl/Makefile index ec819918..9798320c 100644 --- a/hyprctl/Makefile +++ b/hyprctl/Makefile @@ -1,4 +1,4 @@ all: - $(CXX) -std=c++2b ./main.cpp -o ./hyprctl + $(CXX) $(CXXFLAGS) -std=c++2b ./main.cpp -o ./hyprctl clean: rm ./hyprctl From 44accacff934e798b4ce127b009c39004040385a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 22 Nov 2023 19:50:27 +0000 Subject: [PATCH 264/513] config: add nomaximizerequest all to default cfg --- example/hyprland.conf | 1 + src/config/defaultConfig.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/example/hyprland.conf b/example/hyprland.conf index 0f830ec3..caf3ddea 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -120,6 +120,7 @@ device:epic-mouse-v1 { # Example windowrule v2 # windowrulev2 = float,class:^(kitty)$,title:^(kitty)$ # See https://wiki.hyprland.org/Configuring/Window-Rules/ for more +windowrulev2 = nomaximizerequest, .* # You'll probably like this. # See https://wiki.hyprland.org/Configuring/Keywords/ for more diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index e190fb3f..46d7095d 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -127,6 +127,7 @@ device:epic-mouse-v1 { # Example windowrule v2 # windowrulev2 = float,class:^(kitty)$,title:^(kitty)$ # See https://wiki.hyprland.org/Configuring/Window-Rules/ for more +windowrulev2 = nomaximizerequest, .* # You'll probably like this. # See https://wiki.hyprland.org/Configuring/Keywords/ for more From 812a3f6d78681abbfbc0b01f3b5956c38ae06c1c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 22 Nov 2023 20:05:50 +0000 Subject: [PATCH 265/513] renderer: fix double render of tiled on workspace switch fixes #3889 --- src/render/Renderer.cpp | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index cd710137..3a5fa0b6 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -256,6 +256,9 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) continue; + if (pWorkspace->m_bIsSpecialWorkspace && w->m_iWorkspaceID != pWorkspace->m_iID) + continue; + // render active window after all others of this pass if (w.get() == g_pCompositor->m_pLastWindow) { lastWindow = w.get(); @@ -277,6 +280,9 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork if (w->m_bIsFloating) continue; // floating are in the second pass + if (pWorkspace->m_bIsSpecialWorkspace && w->m_iWorkspaceID != pWorkspace->m_iID) + continue; + if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) continue; @@ -301,21 +307,6 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork // render the bad boy renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL); } - - // pinned always above - for (auto& w : g_pCompositor->m_vWindows) { - if (w->isHidden() && !w->m_bIsMapped && !w->m_bFadingOut) - continue; - - if (!w->m_bPinned || !w->m_bIsFloating) - continue; - - if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) - continue; - - // render the bad boy - renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL); - } } void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* time, bool decorate, eRenderPassMode mode, bool ignorePosition, bool ignoreAllGeometry) { @@ -680,6 +671,21 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* renderWorkspaceWindows(pMonitor, ws.get(), time); } + // pinned always above + for (auto& w : g_pCompositor->m_vWindows) { + if (w->isHidden() && !w->m_bIsMapped && !w->m_bFadingOut) + continue; + + if (!w->m_bPinned || !w->m_bIsFloating) + continue; + + if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) + continue; + + // render the bad boy + renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL); + } + EMIT_HOOK_EVENT("render", RENDER_POST_WINDOWS); // Render surfaces above windows for monitor From 45ebe0df8fd0fd4b649728266f65aa48ac307e96 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 22 Nov 2023 23:38:14 +0000 Subject: [PATCH 266/513] config: fix red warn in default config fixes #3917 --- example/hyprland.conf | 2 +- src/config/defaultConfig.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index caf3ddea..7560fefe 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -120,7 +120,7 @@ device:epic-mouse-v1 { # Example windowrule v2 # windowrulev2 = float,class:^(kitty)$,title:^(kitty)$ # See https://wiki.hyprland.org/Configuring/Window-Rules/ for more -windowrulev2 = nomaximizerequest, .* # You'll probably like this. +windowrulev2 = nomaximizerequest, class:.* # You'll probably like this. # See https://wiki.hyprland.org/Configuring/Keywords/ for more diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 46d7095d..6a859220 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -127,7 +127,7 @@ device:epic-mouse-v1 { # Example windowrule v2 # windowrulev2 = float,class:^(kitty)$,title:^(kitty)$ # See https://wiki.hyprland.org/Configuring/Window-Rules/ for more -windowrulev2 = nomaximizerequest, .* # You'll probably like this. +windowrulev2 = nomaximizerequest, class:.* # You'll probably like this. # See https://wiki.hyprland.org/Configuring/Keywords/ for more From e55c5a916ab942e641339471bc80b6d2efbc2044 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 22 Nov 2023 23:43:46 +0000 Subject: [PATCH 267/513] renderer: make sure lastWindow has correct ws in renderWorkspaceWindows fixes #3916 fixes #3888 --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 3a5fa0b6..43616868 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -260,7 +260,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork continue; // render active window after all others of this pass - if (w.get() == g_pCompositor->m_pLastWindow) { + if (w.get() == g_pCompositor->m_pLastWindow && w->m_iWorkspaceID == pWorkspace->m_iID) { lastWindow = w.get(); continue; } From e40e486f61f2643578b9977b86f408799dbc75fd Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 23 Nov 2023 11:31:52 +0000 Subject: [PATCH 268/513] renderer: better checks for special rendering in renderWorkspaceWindows ref #3916 #3888 --- src/render/Renderer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 43616868..73c6ca25 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -256,7 +256,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) continue; - if (pWorkspace->m_bIsSpecialWorkspace && w->m_iWorkspaceID != pWorkspace->m_iID) + if (w->m_iMonitorID == pWorkspace->m_iMonitorID && g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID) && !pWorkspace->m_bIsSpecialWorkspace) continue; // render active window after all others of this pass @@ -280,7 +280,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork if (w->m_bIsFloating) continue; // floating are in the second pass - if (pWorkspace->m_bIsSpecialWorkspace && w->m_iWorkspaceID != pWorkspace->m_iID) + if (w->m_iMonitorID == pWorkspace->m_iMonitorID && g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID) && !pWorkspace->m_bIsSpecialWorkspace) continue; if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) @@ -301,7 +301,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) continue; - if (pWorkspace->m_bIsSpecialWorkspace && w->m_iWorkspaceID != pWorkspace->m_iID) + if (w->m_iMonitorID == pWorkspace->m_iMonitorID && g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID) && !pWorkspace->m_bIsSpecialWorkspace) continue; // render the bad boy From 2ebfd0c7456eff7e9c03d379d1dfbc611dc26672 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Fri, 24 Nov 2023 10:54:21 +0000 Subject: [PATCH 269/513] renderer: Move to a full Hyprland GL rendering pipeline (#3920) Also updates wlroots --- .github/workflows/ci.yaml | 2 +- CMakeLists.txt | 2 +- flake.lock | 8 +- flake.nix | 2 +- src/Compositor.cpp | 5 +- src/Compositor.hpp | 4 +- src/debug/TracyDefines.hpp | 9 -- src/events/Events.hpp | 6 +- src/events/Misc.cpp | 14 --- src/events/Windows.cpp | 2 +- src/helpers/Monitor.cpp | 9 ++ src/helpers/Monitor.hpp | 46 ++++----- src/helpers/Region.cpp | 9 ++ src/helpers/Region.hpp | 2 + src/includes.hpp | 4 +- src/managers/XWaylandManager.cpp | 10 +- src/protocols/Screencopy.cpp | 22 ++--- src/protocols/ToplevelExport.cpp | 62 +++--------- src/render/Framebuffer.cpp | 15 +++ src/render/Framebuffer.hpp | 1 + src/render/OpenGL.cpp | 109 ++++++++++++--------- src/render/OpenGL.hpp | 22 +++-- src/render/Renderbuffer.cpp | 81 +++++++++++++++ src/render/Renderbuffer.hpp | 25 +++++ src/render/Renderer.cpp | 163 ++++++++++++++++++++++++------- src/render/Renderer.hpp | 45 ++++++--- subprojects/wlroots | 2 +- subprojects/wlroots.wrap | 2 +- 28 files changed, 453 insertions(+), 230 deletions(-) create mode 100644 src/render/Renderbuffer.cpp create mode 100644 src/render/Renderbuffer.hpp diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b8093491..a78b7522 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -40,7 +40,7 @@ jobs: cp ./LICENSE hyprland/ cp build/Hyprland hyprland/ cp build/hyprctl/hyprctl hyprland/ - cp subprojects/wlroots/build/libwlroots.so.12032 hyprland/ + cp subprojects/wlroots/build/libwlroots.so.13032 hyprland/ cp build/Hyprland hyprland/ cp -r example/ hyprland/ cp -r assets/ hyprland/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 3bdbb0da..95d5a297 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,7 +57,7 @@ ExternalProject_Add( wlroots PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots - PATCH_COMMAND sed -E -i -e "s/(soversion = 12)([^032]|$$)/soversion = 12032/g" meson.build + PATCH_COMMAND sed -E -i -e "s/(soversion = 13)([^032]|$$)/soversion = 13032/g" meson.build CONFIGURE_COMMAND meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $,-Db_sanitize=address,-Db_sanitize=none> && meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $,-Db_sanitize=address,-Db_sanitize=none> --reconfigure BUILD_COMMAND ninja -C build BUILD_ALWAYS true diff --git a/flake.lock b/flake.lock index fcb03328..d1a8c037 100644 --- a/flake.lock +++ b/flake.lock @@ -67,18 +67,18 @@ "flake": false, "locked": { "host": "gitlab.freedesktop.org", - "lastModified": 1699292815, - "narHash": "sha256-HXu98PyBMKEWLqiTb8viuLDznud/SdkdJsx5A5CWx7I=", + "lastModified": 1700736101, + "narHash": "sha256-1Fh1xf/JX5zFbGIF9LDaffaleG6JDwwwnKby0LyiXEA=", "owner": "wlroots", "repo": "wlroots", - "rev": "5de9e1a99d6642c2d09d589aa37ff0a8945dcee1", + "rev": "f1762f428b0ef2989c81f57ea9e810403d34d946", "type": "gitlab" }, "original": { "host": "gitlab.freedesktop.org", "owner": "wlroots", "repo": "wlroots", - "rev": "5de9e1a99d6642c2d09d589aa37ff0a8945dcee1", + "rev": "f1762f428b0ef2989c81f57ea9e810403d34d946", "type": "gitlab" } }, diff --git a/flake.nix b/flake.nix index f2602105..716648be 100644 --- a/flake.nix +++ b/flake.nix @@ -12,7 +12,7 @@ host = "gitlab.freedesktop.org"; owner = "wlroots"; repo = "wlroots"; - rev = "5de9e1a99d6642c2d09d589aa37ff0a8945dcee1"; + rev = "f1762f428b0ef2989c81f57ea9e810403d34d946"; flake = false; }; diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 1b27a0f4..42b620fe 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -225,7 +225,6 @@ void CCompositor::initServer() { m_sWLROutputMgr = wlr_output_manager_v1_create(m_sWLDisplay); - m_sWLRInhibitMgr = wlr_input_inhibit_manager_create(m_sWLDisplay); m_sWLRKbShInhibitMgr = wlr_keyboard_shortcuts_inhibit_v1_create(m_sWLDisplay); m_sWLRPointerConstraints = wlr_pointer_constraints_v1_create(m_sWLDisplay); @@ -283,7 +282,7 @@ void CCompositor::initServer() { void CCompositor::initAllSignals() { addWLSignal(&m_sWLRBackend->events.new_output, &Events::listen_newOutput, m_sWLRBackend, "Backend"); - addWLSignal(&m_sWLRXDGShell->events.new_surface, &Events::listen_newXDGSurface, m_sWLRXDGShell, "XDG Shell"); + addWLSignal(&m_sWLRXDGShell->events.new_surface, &Events::listen_newXDGToplevel, m_sWLRXDGShell, "XDG Shell"); addWLSignal(&m_sWLRCursor->events.motion, &Events::listen_mouseMove, m_sWLRCursor, "WLRCursor"); addWLSignal(&m_sWLRCursor->events.motion_absolute, &Events::listen_mouseMoveAbsolute, m_sWLRCursor, "WLRCursor"); addWLSignal(&m_sWLRCursor->events.button, &Events::listen_mouseButton, m_sWLRCursor, "WLRCursor"); @@ -312,8 +311,6 @@ void CCompositor::initAllSignals() { addWLSignal(&m_sWLROutputLayout->events.change, &Events::listen_change, m_sWLROutputLayout, "OutputLayout"); addWLSignal(&m_sWLROutputMgr->events.apply, &Events::listen_outputMgrApply, m_sWLROutputMgr, "OutputMgr"); addWLSignal(&m_sWLROutputMgr->events.test, &Events::listen_outputMgrTest, m_sWLROutputMgr, "OutputMgr"); - addWLSignal(&m_sWLRInhibitMgr->events.activate, &Events::listen_InhibitActivate, m_sWLRInhibitMgr, "InhibitMgr"); - addWLSignal(&m_sWLRInhibitMgr->events.deactivate, &Events::listen_InhibitDeactivate, m_sWLRInhibitMgr, "InhibitMgr"); addWLSignal(&m_sWLRPointerConstraints->events.new_constraint, &Events::listen_newConstraint, m_sWLRPointerConstraints, "PointerConstraints"); addWLSignal(&m_sWLRXDGDecoMgr->events.new_toplevel_decoration, &Events::listen_NewXDGDeco, m_sWLRXDGDecoMgr, "XDGDecoMgr"); addWLSignal(&m_sWLRVirtPtrMgr->events.new_virtual_pointer, &Events::listen_newVirtPtr, m_sWLRVirtPtrMgr, "VirtPtrMgr"); diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 829b7e79..d39725aa 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -29,7 +29,8 @@ #include "plugins/PluginSystem.hpp" #include "helpers/Watchdog.hpp" -enum eManagersInitStage { +enum eManagersInitStage +{ STAGE_PRIORITY = 0, STAGE_LATE }; @@ -61,7 +62,6 @@ class CCompositor { wlr_virtual_keyboard_manager_v1* m_sWLRVKeyboardMgr; wlr_output_manager_v1* m_sWLROutputMgr; wlr_presentation* m_sWLRPresentation; - wlr_input_inhibit_manager* m_sWLRInhibitMgr; wlr_keyboard_shortcuts_inhibit_manager_v1* m_sWLRKbShInhibitMgr; wlr_egl* m_sWLREGL; int m_iDRMFD; diff --git a/src/debug/TracyDefines.hpp b/src/debug/TracyDefines.hpp index 767b1a20..49d296f6 100644 --- a/src/debug/TracyDefines.hpp +++ b/src/debug/TracyDefines.hpp @@ -13,15 +13,6 @@ inline PFNGLGETQUERYOBJECTUI64VEXTPROC glGetQueryObjectui64v; #include "../../subprojects/tracy/public/tracy/TracyOpenGL.hpp" -inline void loadGLProc(void* pProc, const char* name) { - void* proc = (void*)eglGetProcAddress(name); - if (proc == NULL) { - Debug::log(CRIT, "[Tracy GPU Profiling] eglGetProcAddress({}) failed", name); - abort(); - } - *(void**)pProc = proc; -} - #define TRACY_GPU_CONTEXT TracyGpuContext #define TRACY_GPU_ZONE(e) TracyGpuZone(e) #define TRACY_GPU_COLLECT TracyGpuCollect diff --git a/src/events/Events.hpp b/src/events/Events.hpp index 371586cc..777bdf9f 100644 --- a/src/events/Events.hpp +++ b/src/events/Events.hpp @@ -42,7 +42,7 @@ namespace Events { DYNLISTENFUNC(repositionPopupXDG); // Surface XDG (window) - LISTENER(newXDGSurface); + LISTENER(newXDGToplevel); LISTENER(activateXDG); // Window events @@ -121,10 +121,6 @@ namespace Events { DYNLISTENFUNC(destroyDragIcon); DYNLISTENFUNC(commitDragIcon); - // Inhibit - LISTENER(InhibitActivate); - LISTENER(InhibitDeactivate); - // Deco XDG LISTENER(NewXDGDeco); diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp index 1df4be3a..91a0ebda 100644 --- a/src/events/Misc.cpp +++ b/src/events/Misc.cpp @@ -156,20 +156,6 @@ void Events::listener_commitDragIcon(void* owner, void* data) { Debug::log(LOG, "Drag icon committed."); } -void Events::listener_InhibitActivate(wl_listener* listener, void* data) { - Debug::log(LOG, "Activated exclusive for {:x}.", (uintptr_t)g_pCompositor->m_sSeat.exclusiveClient); - - g_pInputManager->refocus(); - g_pCompositor->m_sSeat.exclusiveClient = g_pCompositor->m_sWLRInhibitMgr->active_client; -} - -void Events::listener_InhibitDeactivate(wl_listener* listener, void* data) { - Debug::log(LOG, "Deactivated exclusive."); - - g_pCompositor->m_sSeat.exclusiveClient = nullptr; - g_pInputManager->refocus(); -} - void Events::listener_RendererDestroy(wl_listener* listener, void* data) { Debug::log(LOG, "!!Renderer destroyed!!"); } diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 39678154..556ec1b5 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -1169,7 +1169,7 @@ void Events::listener_surfaceXWayland(wl_listener* listener, void* data) { PNEWWINDOW->hyprListener_configureX11.initCallback(&XWSURFACE->events.request_configure, &Events::listener_configureX11, PNEWWINDOW, "XWayland Window"); } -void Events::listener_newXDGSurface(wl_listener* listener, void* data) { +void Events::listener_newXDGToplevel(wl_listener* listener, void* data) { // A window got opened const auto XDGSURFACE = (wlr_xdg_surface*)data; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 20880d8d..833a7a5a 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -643,3 +643,12 @@ void CMonitor::moveTo(const Vector2D& pos) { Vector2D CMonitor::middle() { return vecPosition + vecSize / 2.f; } + +void CMonitor::updateMatrix() { + wlr_matrix_identity(projMatrix.data()); + if (transform != WL_OUTPUT_TRANSFORM_NORMAL) { + wlr_matrix_translate(projMatrix.data(), vecTransformedSize.x / 2.0, vecTransformedSize.y / 2.0); + wlr_matrix_transform(projMatrix.data(), transform); + wlr_matrix_translate(projMatrix.data(), -vecTransformedSize.x / 2.0, -vecTransformedSize.y / 2.0); + } +} \ No newline at end of file diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 2aa7e7eb..f354ca6d 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -50,32 +50,33 @@ class CMonitor { drmModeModeInfo customDrmMode = {}; // WLR stuff - wlr_damage_ring damage; - wlr_output* output = nullptr; - float refreshRate = 60; - int framesToSkip = 0; - int forceFullFrames = 0; - bool noFrameSchedule = false; - bool scheduledRecalc = false; - wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; - bool gammaChanged = false; - float xwaylandScale = 1.f; + wlr_damage_ring damage; + wlr_output* output = nullptr; + float refreshRate = 60; + int framesToSkip = 0; + int forceFullFrames = 0; + bool noFrameSchedule = false; + bool scheduledRecalc = false; + wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; + bool gammaChanged = false; + float xwaylandScale = 1.f; + std::array projMatrix = {0}; - bool dpmsStatus = true; - bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. - bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed. - bool createdByUser = false; - uint32_t drmFormat = DRM_FORMAT_INVALID; - bool isUnsafeFallback = false; + bool dpmsStatus = true; + bool vrrActive = false; // this can be TRUE even if VRR is not active in the case that this display does not support it. + bool enabled10bit = false; // as above, this can be TRUE even if 10 bit failed. + bool createdByUser = false; + uint32_t drmFormat = DRM_FORMAT_INVALID; + bool isUnsafeFallback = false; - bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after - bool renderingActive = false; + bool pendingFrame = false; // if we schedule a frame during rendering, reschedule it after + bool renderingActive = false; - wl_event_source* renderTimer = nullptr; // for RAT - bool RATScheduled = false; - CTimer lastPresentationTimer; + wl_event_source* renderTimer = nullptr; // for RAT + bool RATScheduled = false; + CTimer lastPresentationTimer; - SMonitorRule activeMonitorRule; + SMonitorRule activeMonitorRule; // mirroring CMonitor* pMirrorOf = nullptr; @@ -123,6 +124,7 @@ class CMonitor { void setSpecialWorkspace(const int& id); void moveTo(const Vector2D& pos); Vector2D middle(); + void updateMatrix(); bool m_bEnabled = false; bool m_bRenderingInitPassed = false; diff --git a/src/helpers/Region.cpp b/src/helpers/Region.cpp index 06b8536c..df7de442 100644 --- a/src/helpers/Region.cpp +++ b/src/helpers/Region.cpp @@ -93,6 +93,15 @@ CRegion& CRegion::translate(const Vector2D& vec) { return *this; } +CRegion& CRegion::transform(const wl_output_transform t, double w, double h) { + wlr_region_transform(&m_rRegion, &m_rRegion, t, w, h); + return *this; +} + +CRegion CRegion::copy() const { + return CRegion(*this); +} + CRegion& CRegion::scale(float scale) { wlr_region_scale(&m_rRegion, &m_rRegion, scale); return *this; diff --git a/src/helpers/Region.hpp b/src/helpers/Region.hpp index 1c6923df..7554aa58 100644 --- a/src/helpers/Region.hpp +++ b/src/helpers/Region.hpp @@ -45,12 +45,14 @@ class CRegion { CRegion& intersect(const CRegion& other); CRegion& intersect(double x, double y, double w, double h); CRegion& translate(const Vector2D& vec); + CRegion& transform(const wl_output_transform t, double w, double h); CRegion& invert(pixman_box32_t* box); CRegion& scale(float scale); CBox getExtents(); bool containsPoint(const Vector2D& vec) const; bool empty() const; Vector2D closestPoint(const Vector2D& vec) const; + CRegion copy() const; std::vector getRects() const; diff --git a/src/includes.hpp b/src/includes.hpp index a89f0950..611e4a5c 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -70,7 +70,6 @@ extern "C" { #include #include #include -#include #include #include #include @@ -106,6 +105,9 @@ extern "C" { #include #include #include +#include +#include +#include #include diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index f13b2cd2..2883f205 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -45,10 +45,11 @@ void CHyprXWaylandManager::activateSurface(wlr_surface* pSurface, bool activate) wlr_xdg_toplevel_set_activated(PSURF->toplevel, activate); } else if (wlr_xwayland_surface_try_from_wlr_surface(pSurface)) { - wlr_xwayland_surface_activate(wlr_xwayland_surface_try_from_wlr_surface(pSurface), activate); + const auto XSURF = wlr_xwayland_surface_try_from_wlr_surface(pSurface); + wlr_xwayland_surface_activate(XSURF, activate); - if (activate) - wlr_xwayland_surface_restack(wlr_xwayland_surface_try_from_wlr_surface(pSurface), nullptr, XCB_STACK_MODE_ABOVE); + if (activate && !XSURF->override_redirect) + wlr_xwayland_surface_restack(XSURF, nullptr, XCB_STACK_MODE_ABOVE); } } @@ -58,7 +59,8 @@ void CHyprXWaylandManager::activateWindow(CWindow* pWindow, bool activate) { if (activate) { wlr_xwayland_surface_set_minimized(pWindow->m_uSurface.xwayland, false); - wlr_xwayland_surface_restack(pWindow->m_uSurface.xwayland, nullptr, XCB_STACK_MODE_ABOVE); + if (!pWindow->m_uSurface.xwayland->override_redirect) + wlr_xwayland_surface_restack(pWindow->m_uSurface.xwayland, nullptr, XCB_STACK_MODE_ABOVE); } wlr_xwayland_surface_activate(pWindow->m_uSurface.xwayland, activate); diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 12170595..cff84fc5 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -448,25 +448,19 @@ bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) { if (!sourceTex) return false; - float glMatrix[9]; - wlr_matrix_identity(glMatrix); - wlr_matrix_translate(glMatrix, -frame->box.x, -frame->box.y); - wlr_matrix_scale(glMatrix, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y); + CRegion fakeDamage = {0, 0, frame->box.width, frame->box.height}; - if (!wlr_renderer_begin_with_buffer(g_pCompositor->m_sWLRRenderer, frame->buffer)) { - Debug::log(ERR, "[sc] dmabuf: Client requested a copy to a buffer that failed to pass wlr_renderer_begin_with_buffer"); - wlr_texture_destroy(sourceTex); + if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer)) return false; - } - float color[] = {0, 0, 0, 0}; - wlr_renderer_clear(g_pCompositor->m_sWLRRenderer, color); - // TODO: use hl render methods to use damage - wlr_render_texture_with_matrix(g_pCompositor->m_sWLRRenderer, sourceTex, glMatrix, 1.0f); + CBox monbox = CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y}.translate({-frame->box.x, -frame->box.y}); + g_pHyprOpenGL->setMonitorTransformEnabled(false); + g_pHyprOpenGL->renderTexture(sourceTex, &monbox, 1); + g_pHyprOpenGL->setMonitorTransformEnabled(true); + + g_pHyprRenderer->endRender(); wlr_texture_destroy(sourceTex); - wlr_renderer_end(g_pCompositor->m_sWLRRenderer); - return true; } diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 3f442781..db602396 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -134,7 +134,8 @@ void CToplevelExportProtocolManager::removeFrame(SScreencopyFrame* frame, bool f std::erase_if(m_vFramesAwaitingWrite, [&](const auto& other) { return other == frame; }); wl_resource_set_user_data(frame->resource, nullptr); - wlr_buffer_unlock(frame->buffer); + if (frame->buffer && frame->buffer->n_locks > 0) + wlr_buffer_unlock(frame->buffer); removeClient(frame->client, force); m_lFrames.remove(*frame); } @@ -362,18 +363,14 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times const auto PMONITOR = g_pCompositor->getMonitorFromID(frame->pWindow->m_iMonitorID); CRegion fakeDamage{0, 0, PMONITOR->vecPixelSize.x * 10, PMONITOR->vecPixelSize.y * 10}; - if (frame->overlayCursor) - wlr_output_lock_software_cursors(PMONITOR->output, true); - - if (!wlr_output_attach_render(PMONITOR->output, nullptr)) { - Debug::log(ERR, "[toplevel_export] Couldn't attach render"); + if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE)) { wlr_buffer_end_data_ptr_access(frame->buffer); - if (frame->overlayCursor) - wlr_output_lock_software_cursors(PMONITOR->output, false); return false; } - g_pHyprOpenGL->begin(PMONITOR, &fakeDamage, true); + if (frame->overlayCursor) + wlr_output_lock_software_cursors(PMONITOR->output, true); + g_pHyprOpenGL->clear(CColor(0, 0, 0, 1.0)); // render client at 0,0 @@ -381,46 +378,25 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times g_pHyprRenderer->renderWindow(frame->pWindow, PMONITOR, now, false, RENDER_PASS_ALL, true, true); g_pHyprRenderer->m_bBlockSurfaceFeedback = false; - if (frame->overlayCursor && wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y)) { - // hack le massive - wlr_output_cursor* cursor; - const auto OFFSET = frame->pWindow->m_vRealPosition.vec() - PMONITOR->vecPosition; - wl_list_for_each(cursor, &PMONITOR->output->cursors, link) { - if (!cursor->enabled || !cursor->visible || PMONITOR->output->hardware_cursor == cursor) { - continue; - } - cursor->x -= OFFSET.x; - cursor->y -= OFFSET.y; - } - wlr_output_render_software_cursors(PMONITOR->output, NULL); - wl_list_for_each(cursor, &PMONITOR->output->cursors, link) { - if (!cursor->enabled || !cursor->visible || PMONITOR->output->hardware_cursor == cursor) { - continue; - } - cursor->x += OFFSET.x; - cursor->y += OFFSET.y; - } - wlr_renderer_end(g_pCompositor->m_sWLRRenderer); - } + if (frame->overlayCursor) + g_pHyprRenderer->renderSoftwareCursors(PMONITOR, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.vec()); // copy pixels const auto PFORMAT = gles2FromDRM(format); if (!PFORMAT) { Debug::log(ERR, "[toplevel_export] Cannot read pixels, unsupported format {:x}", (uintptr_t)PFORMAT); - g_pHyprOpenGL->end(); + g_pHyprRenderer->endRender(); wlr_buffer_end_data_ptr_access(frame->buffer); if (frame->overlayCursor) wlr_output_lock_software_cursors(PMONITOR->output, false); return false; } - glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_RenderData.pCurrentMonData->primaryFB.m_iFb); + g_pHyprOpenGL->m_RenderData.mainFB->bind(); glReadPixels(0, 0, frame->box.width, frame->box.height, PFORMAT->gl_format, PFORMAT->gl_type, data); - g_pHyprOpenGL->end(); - - wlr_output_rollback(PMONITOR->output); + g_pHyprRenderer->endRender(); wlr_buffer_end_data_ptr_access(frame->buffer); @@ -431,14 +407,12 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times } bool CToplevelExportProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame, timespec* now) { - if (!wlr_renderer_begin_with_buffer(g_pCompositor->m_sWLRRenderer, frame->buffer)) - return false; - const auto PMONITOR = g_pCompositor->getMonitorFromID(frame->pWindow->m_iMonitorID); CRegion fakeDamage{0, 0, INT16_MAX, INT16_MAX}; - g_pHyprOpenGL->begin(PMONITOR, &fakeDamage, true); + if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_TO_BUFFER, frame->buffer)) + return false; g_pHyprOpenGL->clear(CColor(0, 0, 0, 1.0)); @@ -446,14 +420,10 @@ bool CToplevelExportProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame, ti g_pHyprRenderer->renderWindow(frame->pWindow, PMONITOR, now, false, RENDER_PASS_ALL, true, true); g_pHyprRenderer->m_bBlockSurfaceFeedback = false; - g_pHyprOpenGL->bindWlrOutputFb(); + if (frame->overlayCursor) + g_pHyprRenderer->renderSoftwareCursors(PMONITOR, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.vec()); - CBox monbox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y}; - g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 1.f); - - g_pHyprOpenGL->end(); - - wlr_renderer_end(g_pCompositor->m_sWLRRenderer); + g_pHyprRenderer->endRender(); return true; } diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp index 1ebbc585..94b3f64a 100644 --- a/src/render/Framebuffer.cpp +++ b/src/render/Framebuffer.cpp @@ -62,6 +62,21 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { return true; } +void CFramebuffer::addStencil() { + glBindTexture(GL_TEXTURE_2D, m_pStencilTex->m_iTexID); + glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_vSize.x, m_vSize.y, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0); + + glBindFramebuffer(GL_FRAMEBUFFER, m_iFb); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_pStencilTex->m_iTexID, 0); + + auto status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + RASSERT((status == GL_FRAMEBUFFER_COMPLETE), "Failed adding a stencil to fbo!", status); + + glBindTexture(GL_TEXTURE_2D, 0); + glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_iCurrentOutputFb); +} + void CFramebuffer::bind() { #ifndef GLES2 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_iFb); diff --git a/src/render/Framebuffer.hpp b/src/render/Framebuffer.hpp index 73b70431..22809158 100644 --- a/src/render/Framebuffer.hpp +++ b/src/render/Framebuffer.hpp @@ -8,6 +8,7 @@ class CFramebuffer { ~CFramebuffer(); bool alloc(int w, int h, uint32_t format = GL_RGBA); + void addStencil(); void bind(); void release(); void reset(); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 7cfe2c53..119d522b 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -5,6 +5,15 @@ #include "Shaders.hpp" #include +inline void loadGLProc(void* pProc, const char* name) { + void* proc = (void*)eglGetProcAddress(name); + if (proc == NULL) { + Debug::log(CRIT, "[Tracy GPU Profiling] eglGetProcAddress({}) failed", name); + abort(); + } + *(void**)pProc = proc; +} + CHyprOpenGLImpl::CHyprOpenGLImpl() { RASSERT(eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)), "Couldn't unset current EGL!"); @@ -23,6 +32,9 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() { Debug::log(LOG, "Renderer: {}", (char*)glGetString(GL_RENDERER)); Debug::log(LOG, "Supported extensions size: {}", std::count(m_szExtensions.begin(), m_szExtensions.end(), ' ')); + loadGLProc(&m_sProc.glEGLImageTargetRenderbufferStorageOES, "glEGLImageTargetRenderbufferStorageOES"); + loadGLProc(&m_sProc.eglDestroyImageKHR, "eglDestroyImageKHR"); + #ifdef USE_TRACY_GPU loadGLProc(&glQueryCounter, "glQueryCounterEXT"); @@ -106,11 +118,9 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { m_RenderData.pMonitor = pMonitor; - TRACY_GPU_ZONE("RenderBegin"); + static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue; - if (eglGetCurrentContext() != wlr_egl_get_context(g_pCompositor->m_sWLREGL)) { - eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)); - } + TRACY_GPU_ZONE("RenderBegin"); glViewport(0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); @@ -118,19 +128,16 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { m_RenderData.pCurrentMonData = &m_mMonitorRenderResources[pMonitor]; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &m_iCurrentOutputFb); - m_iWLROutputFb = m_iCurrentOutputFb; - // ensure a framebuffer for the monitor exists - if (!m_mMonitorRenderResources.contains(pMonitor) || m_RenderData.pCurrentMonData->primaryFB.m_vSize != pMonitor->vecPixelSize) { + if (!m_mMonitorRenderResources.contains(pMonitor) || m_RenderData.pCurrentMonData->offloadFB.m_vSize != pMonitor->vecPixelSize) { m_RenderData.pCurrentMonData->stencilTex.allocate(); - m_RenderData.pCurrentMonData->primaryFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; + m_RenderData.pCurrentMonData->offloadFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; m_RenderData.pCurrentMonData->mirrorFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; m_RenderData.pCurrentMonData->mirrorSwapFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; m_RenderData.pCurrentMonData->offMainFB.m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; - m_RenderData.pCurrentMonData->primaryFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); + m_RenderData.pCurrentMonData->offloadFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); m_RenderData.pCurrentMonData->mirrorFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); m_RenderData.pCurrentMonData->mirrorSwapFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); m_RenderData.pCurrentMonData->offMainFB.alloc(pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y, pMonitor->drmFormat); @@ -144,19 +151,37 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { if (!m_RenderData.pCurrentMonData->m_bShadersInitialized) initShaders(); - // bind the primary Hypr Framebuffer - m_RenderData.pCurrentMonData->primaryFB.bind(); - m_RenderData.damage.set(*pDamage); m_bFakeFrame = fake; - m_RenderData.currentFB = &m_RenderData.pCurrentMonData->primaryFB; - if (m_bReloadScreenShader) { m_bReloadScreenShader = false; applyScreenShader(g_pConfigManager->getString("decoration:screen_shader")); } + + const auto PRBO = g_pHyprRenderer->getCurrentRBO(); + + if (m_sFinalScreenShader.program > 0 || m_bFakeFrame || m_RenderData.mouseZoomFactor != 1.0 || pMonitor->vecPixelSize != PRBO->getFB()->m_vSize || + (*PBLUR != 0 && !pMonitor->solitaryClient /* TODO: revisit when possible */)) { + // we have to offload + // bind the primary Hypr Framebuffer + m_RenderData.pCurrentMonData->offloadFB.bind(); + m_RenderData.currentFB = &m_RenderData.pCurrentMonData->offloadFB; + m_bOffloadedFramebuffer = true; + } else { + // we can render to the rbo directly + const auto PFBO = PRBO->getFB(); + m_RenderData.currentFB = PFBO; + if (PFBO->m_pStencilTex != &m_RenderData.pCurrentMonData->stencilTex) { + PFBO->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; + PFBO->addStencil(); + } + PRBO->bindFB(); + m_bOffloadedFramebuffer = false; + } + + m_RenderData.mainFB = m_RenderData.currentFB; } void CHyprOpenGLImpl::end() { @@ -164,14 +189,15 @@ void CHyprOpenGLImpl::end() { TRACY_GPU_ZONE("RenderEnd"); + if (!m_RenderData.pMonitor->mirrors.empty()) + saveBufferForMirror(); // save with original damage region + // end the render, copy the data to the WLR framebuffer - if (!m_bFakeFrame) { + if (m_bOffloadedFramebuffer && !m_bFakeFrame) { m_RenderData.damage = m_RenderData.pMonitor->lastFrameDamage; - if (!m_RenderData.pMonitor->mirrors.empty()) - saveBufferForMirror(); // save with original damage region + g_pHyprRenderer->getCurrentRBO()->bindFB(); - glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb); CBox monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; if (m_RenderData.mouseZoomFactor != 1.f) { @@ -199,9 +225,9 @@ void CHyprOpenGLImpl::end() { blend(false); if (m_sFinalScreenShader.program < 1) - renderTexturePrimitive(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox); + renderTexturePrimitive(m_RenderData.pCurrentMonData->offloadFB.m_cTex, &monbox); else - renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 1.f); + renderTexture(m_RenderData.pCurrentMonData->offloadFB.m_cTex, &monbox, 1.f); blend(true); @@ -212,15 +238,10 @@ void CHyprOpenGLImpl::end() { // reset our data m_RenderData.pMonitor = nullptr; - m_iWLROutputFb = 0; m_RenderData.mouseZoomFactor = 1.f; m_RenderData.mouseZoomUseMouse = true; } -void CHyprOpenGLImpl::bindWlrOutputFb() { - glBindFramebuffer(GL_FRAMEBUFFER, m_iWLROutputFb); -} - void CHyprOpenGLImpl::initShaders() { GLuint prog = createProgram(QUADVERTSRC, QUADFRAGSRC); m_RenderData.pCurrentMonData->m_shQUAD.program = prog; @@ -501,8 +522,7 @@ void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round CFramebuffer* POUTFB = blurMainFramebufferWithDamage(blurA, &damage); - // bind primary - m_RenderData.pCurrentMonData->primaryFB.bind(); + m_RenderData.currentFB->bind(); // make a stencil for rounded corners to work with blur scissor((CBox*)nullptr); // allow the entire window and stencil to render @@ -553,7 +573,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion float matrix[9]; wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, - m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here + m_RenderData.pMonitor->projMatrix.data()); // TODO: write own, don't use WLR here float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -640,7 +660,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox* // get transform const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); float matrix[9]; - wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix); + wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->projMatrix.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -801,7 +821,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, CBox* pBox) { // get transform const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); float matrix[9]; - wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix); + wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->projMatrix.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -855,7 +875,7 @@ void CHyprOpenGLImpl::renderTextureMatte(const CTexture& tex, CBox* pBox, CFrame // get transform const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); float matrix[9]; - wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix); + wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->projMatrix.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -914,7 +934,7 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o const auto TRANSFORM = wlr_output_transform_invert(m_RenderData.pMonitor->transform); float matrix[9]; CBox MONITORBOX = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; - wlr_matrix_project_box(matrix, MONITORBOX.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->output->transform_matrix); + wlr_matrix_project_box(matrix, MONITORBOX.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->projMatrix.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -947,9 +967,9 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o glActiveTexture(GL_TEXTURE0); - glBindTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTarget, m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTexID); + glBindTexture(m_RenderData.currentFB->m_cTex.m_iTarget, m_RenderData.currentFB->m_cTex.m_iTexID); - glTexParameteri(m_RenderData.pCurrentMonData->primaryFB.m_cTex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(m_RenderData.currentFB->m_cTex.m_iTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glUseProgram(m_RenderData.pCurrentMonData->m_shBLURPREPARE.program); @@ -1225,7 +1245,7 @@ void CHyprOpenGLImpl::preBlurForCurrentMonitor() { renderTextureInternalWithDamage(POUTFB->m_cTex, &wholeMonitor, 1, &fakeDamage, 0, false, true, false); m_bEndFrame = false; - m_RenderData.pCurrentMonData->primaryFB.bind(); + m_RenderData.currentFB->bind(); m_RenderData.pCurrentMonData->blurFBDirty = false; @@ -1321,8 +1341,7 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, flo POUTFB = &m_RenderData.pCurrentMonData->blurFB; } - // bind primary - m_RenderData.pCurrentMonData->primaryFB.bind(); + m_RenderData.currentFB->bind(); // make a stencil for rounded corners to work with blur scissor((CBox*)nullptr); // allow the entire window and stencil to render @@ -1404,7 +1423,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in float matrix[9]; wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, - m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here + m_RenderData.pMonitor->projMatrix.data()); // TODO: write own, don't use WLR here float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -1744,7 +1763,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const float matrix[9]; wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, - m_RenderData.pMonitor->output->transform_matrix); // TODO: write own, don't use WLR here + m_RenderData.pMonitor->projMatrix.data()); // TODO: write own, don't use WLR here float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -1811,11 +1830,11 @@ void CHyprOpenGLImpl::saveBufferForMirror() { blend(false); - renderTexture(m_RenderData.pCurrentMonData->primaryFB.m_cTex, &monbox, 1.f, 0, false, false); + renderTexture(m_RenderData.currentFB->m_cTex, &monbox, 1.f, 0, false, false); blend(true); - m_RenderData.pCurrentMonData->primaryFB.bind(); + m_RenderData.currentFB->bind(); } void CHyprOpenGLImpl::renderMirrored() { @@ -1974,7 +1993,7 @@ void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) { wlr_output_attach_render(pMonitor->output, nullptr); g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].mirrorFB.release(); - g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].primaryFB.release(); + g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].offloadFB.release(); g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].mirrorSwapFB.release(); g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].monitorMirrorFB.release(); g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].blurFB.release(); @@ -2014,8 +2033,8 @@ void CHyprOpenGLImpl::renderOffToMain(CFramebuffer* off) { } void CHyprOpenGLImpl::bindBackOnMain() { - m_RenderData.pCurrentMonData->primaryFB.bind(); - m_RenderData.currentFB = &m_RenderData.pCurrentMonData->primaryFB; + m_RenderData.mainFB->bind(); + m_RenderData.currentFB = m_RenderData.mainFB; } void CHyprOpenGLImpl::setMonitorTransformEnabled(bool enabled) { diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 8c412302..4311e16c 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -14,6 +14,9 @@ #include "Texture.hpp" #include "Framebuffer.hpp" #include "Transformer.hpp" +#include "Renderbuffer.hpp" + +#include #include "../debug/TracyDefines.hpp" @@ -39,7 +42,7 @@ struct SRenderModifData { }; struct SMonitorRenderData { - CFramebuffer primaryFB; + CFramebuffer offloadFB; CFramebuffer mirrorFB; // these are used for some effects, CFramebuffer mirrorSwapFB; // etc CFramebuffer offMainFB; @@ -80,6 +83,7 @@ struct SCurrentRenderData { SMonitorRenderData* pCurrentMonData = nullptr; CFramebuffer* currentFB = nullptr; + CFramebuffer* mainFB = nullptr; CRegion damage; @@ -105,7 +109,6 @@ class CHyprOpenGLImpl { void begin(CMonitor*, CRegion*, bool fake = false); void end(); - void bindWlrOutputFb(); void renderRect(CBox*, const CColor&, int round = 0); void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f); @@ -157,7 +160,6 @@ class CHyprOpenGLImpl { SCurrentRenderData m_RenderData; GLint m_iCurrentOutputFb = 0; - GLint m_iWLROutputFb = 0; bool m_bReloadScreenShader = true; // at launch it can be set @@ -169,6 +171,11 @@ class CHyprOpenGLImpl { std::unordered_map m_mMonitorRenderResources; std::unordered_map m_mMonitorBGTextures; + struct { + PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES = nullptr; + PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = nullptr; + } m_sProc; + private: std::list m_lBuffers; std::list m_lTextures; @@ -176,10 +183,11 @@ class CHyprOpenGLImpl { int m_iDRMFD; std::string m_szExtensions; - bool m_bFakeFrame = false; - bool m_bEndFrame = false; - bool m_bApplyFinalShader = false; - bool m_bBlend = false; + bool m_bFakeFrame = false; + bool m_bEndFrame = false; + bool m_bApplyFinalShader = false; + bool m_bBlend = false; + bool m_bOffloadedFramebuffer = false; CShader m_sFinalScreenShader; CTimer m_tGlobalTimer; diff --git a/src/render/Renderbuffer.cpp b/src/render/Renderbuffer.cpp new file mode 100644 index 00000000..0643904b --- /dev/null +++ b/src/render/Renderbuffer.cpp @@ -0,0 +1,81 @@ +#include "Renderbuffer.hpp" +#include "OpenGL.hpp" +#include "../Compositor.hpp" + +#include + +CRenderbuffer::~CRenderbuffer() { + if (eglGetCurrentContext() != wlr_egl_get_context(g_pCompositor->m_sWLREGL)) + eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)); + + m_sFramebuffer.release(); + glDeleteRenderbuffers(1, &m_iRBO); + + g_pHyprOpenGL->m_sProc.eglDestroyImageKHR(wlr_egl_get_display(g_pCompositor->m_sWLREGL), m_iImage); +} + +CRenderbuffer::CRenderbuffer(wlr_buffer* buffer, uint32_t format) : m_pWlrBuffer(buffer) { + + // EVIL, but we can't include a hidden header because nixos is fucking special + static EGLImageKHR (*PWLREGLCREATEIMAGEFROMDMABUF)(wlr_egl*, wlr_dmabuf_attributes*, bool*); + static bool symbolFound = false; + if (!symbolFound) { + PWLREGLCREATEIMAGEFROMDMABUF = reinterpret_cast(dlsym(RTLD_DEFAULT, "wlr_egl_create_image_from_dmabuf")); + + symbolFound = true; + + RASSERT(PWLREGLCREATEIMAGEFROMDMABUF, "wlr_egl_create_image_from_dmabuf was not found in wlroots!"); + + Debug::log(LOG, "CRenderbuffer: wlr_egl_create_image_from_dmabuf found at {:x}", (uintptr_t)PWLREGLCREATEIMAGEFROMDMABUF); + } + // end evil hack + + struct wlr_dmabuf_attributes dmabuf = {0}; + if (!wlr_buffer_get_dmabuf(buffer, &dmabuf)) + throw std::runtime_error("wlr_buffer_get_dmabuf failed"); + + bool externalOnly; + m_iImage = PWLREGLCREATEIMAGEFROMDMABUF(g_pCompositor->m_sWLREGL, &dmabuf, &externalOnly); + if (m_iImage == EGL_NO_IMAGE_KHR) + throw std::runtime_error("wlr_egl_create_image_from_dmabuf failed"); + + glGenRenderbuffers(1, &m_iRBO); + glBindRenderbuffer(GL_RENDERBUFFER, m_iRBO); + g_pHyprOpenGL->m_sProc.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, (GLeglImageOES)m_iImage); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + glGenFramebuffers(1, &m_sFramebuffer.m_iFb); + m_sFramebuffer.m_vSize = {buffer->width, buffer->height}; + m_sFramebuffer.bind(); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_iRBO); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + throw std::runtime_error("rbo: glCheckFramebufferStatus failed"); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + hyprListener_destroyBuffer.initCallback( + &buffer->events.destroy, [](void* owner, void* data) { g_pHyprRenderer->onRenderbufferDestroy((CRenderbuffer*)owner); }, this, "CRenderbuffer"); +} + +void CRenderbuffer::bind() { + glBindRenderbuffer(GL_RENDERBUFFER, m_iRBO); + bindFB(); +} + +void CRenderbuffer::bindFB() { + m_sFramebuffer.bind(); +} + +void CRenderbuffer::unbind() { + glBindRenderbuffer(GL_RENDERBUFFER, 0); +#ifndef GLES2 + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +#else + glBindFramebuffer(GL_FRAMEBUFFER, 0); +#endif +} + +CFramebuffer* CRenderbuffer::getFB() { + return &m_sFramebuffer; +} \ No newline at end of file diff --git a/src/render/Renderbuffer.hpp b/src/render/Renderbuffer.hpp new file mode 100644 index 00000000..d8df8ca5 --- /dev/null +++ b/src/render/Renderbuffer.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "Framebuffer.hpp" + +class CMonitor; + +class CRenderbuffer { + public: + CRenderbuffer(wlr_buffer* buffer, uint32_t format); + ~CRenderbuffer(); + + void bind(); + void bindFB(); + void unbind(); + CFramebuffer* getFB(); + + wlr_buffer* m_pWlrBuffer = nullptr; + + DYNLISTENER(destroyBuffer); + + private: + EGLImageKHR m_iImage = 0; + GLuint m_iRBO = 0; + CFramebuffer m_sFramebuffer; +}; \ No newline at end of file diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 73c6ca25..128f36ef 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -845,8 +845,8 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { } void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { - static std::chrono::high_resolution_clock::time_point startRender = std::chrono::high_resolution_clock::now(); - static std::chrono::high_resolution_clock::time_point startRenderOverlay = std::chrono::high_resolution_clock::now(); + static std::chrono::high_resolution_clock::time_point renderStart = std::chrono::high_resolution_clock::now(); + static std::chrono::high_resolution_clock::time_point renderStartOverlay = std::chrono::high_resolution_clock::now(); static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now(); static auto* const PDEBUGOVERLAY = &g_pConfigManager->getConfigValuePtr("debug:overlay")->intValue; @@ -887,7 +887,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { firstLaunchAnimActive = false; } - startRender = std::chrono::high_resolution_clock::now(); + renderStart = std::chrono::high_resolution_clock::now(); if (*PDEBUGOVERLAY == 1) { g_pDebugOverlay->frameData(pMonitor); @@ -991,7 +991,6 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { // check the damage CRegion damage; bool hasChanged = pMonitor->output->needs_frame || pixman_region32_not_empty(&pMonitor->damage.current); - int bufferAge; if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && pMonitor->forceFullFrames == 0 && damageBlinkCleanup == 0) return; @@ -1007,16 +1006,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { if (UNLOCK_SC) wlr_output_lock_software_cursors(pMonitor->output, true); - if (!wlr_output_attach_render(pMonitor->output, &bufferAge)) { - Debug::log(ERR, "Couldn't attach render to display {} ???", pMonitor->szName); - - if (UNLOCK_SC) - wlr_output_lock_software_cursors(pMonitor->output, false); - - return; - } - - wlr_damage_ring_get_buffer_damage(&pMonitor->damage, bufferAge, damage.pixman()); + wlr_damage_ring_get_buffer_damage(&pMonitor->damage, m_iLastBufferAge, damage.pixman()); pMonitor->renderingActive = true; @@ -1062,7 +1052,25 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { TRACY_GPU_ZONE("Render"); - g_pHyprOpenGL->begin(pMonitor, &damage); + if (pMonitor == g_pCompositor->getMonitorFromCursor()) + g_pHyprOpenGL->m_RenderData.mouseZoomFactor = std::clamp(*PZOOMFACTOR, 1.f, INFINITY); + else + g_pHyprOpenGL->m_RenderData.mouseZoomFactor = 1.f; + + if (zoomInFactorFirstLaunch > 1.f) { + g_pHyprOpenGL->m_RenderData.mouseZoomFactor = zoomInFactorFirstLaunch; + g_pHyprOpenGL->m_RenderData.mouseZoomUseMouse = false; + g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false; + } + + if (!beginRender(pMonitor, damage, RENDER_MODE_NORMAL)) { + Debug::log(ERR, "renderer: couldn't beginRender()!"); + + if (UNLOCK_SC) + wlr_output_lock_software_cursors(pMonitor->output, false); + + return; + } EMIT_HOOK_EVENT("render", RENDER_BEGIN); @@ -1097,7 +1105,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { // for drawing the debug overlay if (pMonitor == g_pCompositor->m_vMonitors.front().get() && *PDEBUGOVERLAY == 1) { - startRenderOverlay = std::chrono::high_resolution_clock::now(); + renderStartOverlay = std::chrono::high_resolution_clock::now(); g_pDebugOverlay->draw(); endRenderOverlay = std::chrono::high_resolution_clock::now(); } @@ -1118,35 +1126,22 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { renderCursor = renderCursor && shouldRenderCursor(); - if (renderCursor && wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y)) { + if (renderCursor) { TRACY_GPU_ZONE("RenderCursor"); bool lockSoftware = pMonitor == g_pCompositor->getMonitorFromCursor() && *PZOOMFACTOR != 1.f; if (lockSoftware) { wlr_output_lock_software_cursors(pMonitor->output, true); - wlr_output_render_software_cursors(pMonitor->output, NULL); + g_pHyprRenderer->renderSoftwareCursors(pMonitor, g_pHyprOpenGL->m_RenderData.damage); wlr_output_lock_software_cursors(pMonitor->output, false); } else - wlr_output_render_software_cursors(pMonitor->output, NULL); - - wlr_renderer_end(g_pCompositor->m_sWLRRenderer); - } - - if (pMonitor == g_pCompositor->getMonitorFromCursor()) - g_pHyprOpenGL->m_RenderData.mouseZoomFactor = std::clamp(*PZOOMFACTOR, 1.f, INFINITY); - else - g_pHyprOpenGL->m_RenderData.mouseZoomFactor = 1.f; - - if (zoomInFactorFirstLaunch > 1.f) { - g_pHyprOpenGL->m_RenderData.mouseZoomFactor = zoomInFactorFirstLaunch; - g_pHyprOpenGL->m_RenderData.mouseZoomUseMouse = false; - g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false; + g_pHyprRenderer->renderSoftwareCursors(pMonitor, g_pHyprOpenGL->m_RenderData.damage); } EMIT_HOOK_EVENT("render", RENDER_LAST_MOMENT); - g_pHyprOpenGL->end(); + endRender(); TRACY_GPU_COLLECT; @@ -1192,12 +1187,12 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { pMonitor->pendingFrame = false; - const float µs = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - startRender).count() / 1000.f; + const float µs = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - renderStart).count() / 1000.f; g_pDebugOverlay->renderData(pMonitor, µs); if (*PDEBUGOVERLAY == 1) { if (pMonitor == g_pCompositor->m_vMonitors.front().get()) { - const float µsNoOverlay = µs - std::chrono::duration_cast(endRenderOverlay - startRenderOverlay).count() / 1000.f; + const float µsNoOverlay = µs - std::chrono::duration_cast(endRenderOverlay - renderStartOverlay).count() / 1000.f; g_pDebugOverlay->renderDataNoOverlay(pMonitor, µsNoOverlay); } else { g_pDebugOverlay->renderDataNoOverlay(pMonitor, µs); @@ -1957,6 +1952,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->vecPixelSize = Vector2D(transformedBox.width, transformedBox.height); } + pMonitor->updateMatrix(); + // update renderer (here because it will call rollback, so we cannot do this before committing) g_pHyprOpenGL->destroyMonitorResources(pMonitor); @@ -2191,3 +2188,99 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { // found one! pMonitor->solitaryClient = PCANDIDATE; } + +void CHyprRenderer::renderSoftwareCursors(CMonitor* pMonitor, const CRegion& damage, std::optional overridePos) { + const auto CURSORPOS = overridePos.value_or(g_pInputManager->getMouseCoordsInternal() - pMonitor->vecPosition); + wlr_output_cursor* cursor; + wl_list_for_each(cursor, &pMonitor->output->cursors, link) { + if (!cursor->enabled || !cursor->visible || pMonitor->output->hardware_cursor == cursor) + continue; + + if (!cursor->texture) + continue; + + CBox cursorBox = CBox{CURSORPOS.x, CURSORPOS.y, cursor->width, cursor->height}.translate({-cursor->hotspot_x, -cursor->hotspot_y}); + + g_pHyprOpenGL->renderTexturePrimitive(cursor->texture, &cursorBox); + } +} + +CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(wlr_buffer* buffer, uint32_t fmt) { + auto it = std::find_if(m_vRenderbuffers.begin(), m_vRenderbuffers.end(), [&](const auto& other) { return other->m_pWlrBuffer == buffer; }); + + if (it != m_vRenderbuffers.end()) + return it->get(); + + return m_vRenderbuffers.emplace_back(std::make_unique(buffer, fmt)).get(); +} + +bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, wlr_buffer* withBuffer) { + + if (eglGetCurrentContext() != wlr_egl_get_context(g_pCompositor->m_sWLREGL)) + eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)); + + m_eRenderMode = mode; + + g_pHyprOpenGL->m_RenderData.pMonitor = pMonitor; // has to be set cuz allocs + + if (mode == RENDER_MODE_FULL_FAKE) { + wlr_output_attach_render(pMonitor->output, nullptr); + g_pHyprOpenGL->begin(pMonitor, &damage, true); + return true; + } + + if (!withBuffer) { + if (!wlr_output_configure_primary_swapchain(pMonitor->output, &pMonitor->output->pending, &pMonitor->output->swapchain)) + return false; + + m_pCurrentWlrBuffer = wlr_swapchain_acquire(pMonitor->output->swapchain, &m_iLastBufferAge); + if (!m_pCurrentWlrBuffer) + return false; + } else { + m_pCurrentWlrBuffer = withBuffer; + } + + try { + m_pCurrentRenderbuffer = getOrCreateRenderbuffer(m_pCurrentWlrBuffer, pMonitor->drmFormat); + } catch (std::exception& e) { + wlr_buffer_unlock(m_pCurrentWlrBuffer); + return false; + } + + m_pCurrentRenderbuffer->bind(); + g_pHyprOpenGL->begin(pMonitor, &damage); + + return true; +} + +void CHyprRenderer::endRender() { + const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor; + + g_pHyprOpenGL->end(); + + if (m_eRenderMode == RENDER_MODE_FULL_FAKE) { + wlr_output_rollback(PMONITOR->output); + return; + } + + glFlush(); + + if (m_eRenderMode == RENDER_MODE_NORMAL) + wlr_output_state_set_buffer(&PMONITOR->output->pending, m_pCurrentWlrBuffer); + + wlr_buffer_unlock(m_pCurrentWlrBuffer); + + m_pCurrentRenderbuffer->unbind(); + + m_pCurrentRenderbuffer = nullptr; + m_pCurrentWlrBuffer = nullptr; + m_iLastBufferAge = 0; +} + +void CHyprRenderer::onRenderbufferDestroy(CRenderbuffer* rb) { + std::erase_if(m_vRenderbuffers, [&](const auto& rbo) { return rbo.get() == rb; }); +} + +CRenderbuffer* CHyprRenderer::getCurrentRBO() { + return m_pCurrentRenderbuffer; +} \ No newline at end of file diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index f28600b4..6b4f0561 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -6,6 +6,7 @@ #include "../helpers/Workspace.hpp" #include "../Window.hpp" #include "OpenGL.hpp" +#include "Renderbuffer.hpp" #include "../helpers/Timer.hpp" #include "../helpers/Region.hpp" @@ -27,6 +28,13 @@ enum eRenderPassMode RENDER_PASS_POPUP }; +enum eRenderMode +{ + RENDER_MODE_NORMAL = 0, + RENDER_MODE_FULL_FAKE = 1, + RENDER_MODE_TO_BUFFER = 2 +}; + class CToplevelExportProtocolManager; class CInputManager; struct SSessionLockSurface; @@ -58,6 +66,12 @@ class CHyprRenderer { void recheckSolitaryForMonitor(CMonitor* pMonitor); void setCursorSurface(wlr_surface* surf, int hotspotX, int hotspotY); void setCursorFromName(const std::string& name); + void renderSoftwareCursors(CMonitor* pMonitor, const CRegion& damage, std::optional overridePos = {}); + void onRenderbufferDestroy(CRenderbuffer* rb); + CRenderbuffer* getCurrentRBO(); + + bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, wlr_buffer* withBuffer = nullptr); + void endRender(); bool m_bWindowRequestedCursorHide = false; bool m_bBlockSurfaceFeedback = false; @@ -89,19 +103,26 @@ class CHyprRenderer { } m_sLastCursorData; private: - void arrangeLayerArray(CMonitor*, const std::vector>&, bool, CBox*); - void renderWorkspaceWindowsFullscreen(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) - void renderWorkspaceWindows(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) - void renderWindow(CWindow*, CMonitor*, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool ignoreAllGeometry = false); - void renderLayer(SLayerSurface*, CMonitor*, timespec*); - void renderSessionLockSurface(SSessionLockSurface*, CMonitor*, timespec*); - void renderDragIcon(CMonitor*, timespec*); - void renderIMEPopup(SIMEPopup*, CMonitor*, timespec*); - void renderWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const CBox& geometry); - void renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); + void arrangeLayerArray(CMonitor*, const std::vector>&, bool, CBox*); + void renderWorkspaceWindowsFullscreen(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) + void renderWorkspaceWindows(CMonitor*, CWorkspace*, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) + void renderWindow(CWindow*, CMonitor*, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool ignoreAllGeometry = false); + void renderLayer(SLayerSurface*, CMonitor*, timespec*); + void renderSessionLockSurface(SSessionLockSurface*, CMonitor*, timespec*); + void renderDragIcon(CMonitor*, timespec*); + void renderIMEPopup(SIMEPopup*, CMonitor*, timespec*); + void renderWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const CBox& geometry); + void renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); - bool m_bHasARenderedCursor = true; - bool m_bCursorHasSurface = false; + bool m_bHasARenderedCursor = true; + bool m_bCursorHasSurface = false; + CRenderbuffer* m_pCurrentRenderbuffer = nullptr; + wlr_buffer* m_pCurrentWlrBuffer = nullptr; + eRenderMode m_eRenderMode = RENDER_MODE_NORMAL; + int m_iLastBufferAge = 0; + + CRenderbuffer* getOrCreateRenderbuffer(wlr_buffer* buffer, uint32_t fmt); + std::vector> m_vRenderbuffers; friend class CHyprOpenGLImpl; friend class CToplevelExportProtocolManager; diff --git a/subprojects/wlroots b/subprojects/wlroots index 5de9e1a9..f1762f42 160000 --- a/subprojects/wlroots +++ b/subprojects/wlroots @@ -1 +1 @@ -Subproject commit 5de9e1a99d6642c2d09d589aa37ff0a8945dcee1 +Subproject commit f1762f428b0ef2989c81f57ea9e810403d34d946 diff --git a/subprojects/wlroots.wrap b/subprojects/wlroots.wrap index 7df8166b..94757838 100644 --- a/subprojects/wlroots.wrap +++ b/subprojects/wlroots.wrap @@ -1,7 +1,7 @@ [wrap-git] directory = wlroots url = https://gitlab.freedesktop.org/wlroots/wlroots.git -revision = 5de9e1a99d6642c2d09d589aa37ff0a8945dcee1 +revision = f1762f428b0ef2989c81f57ea9e810403d34d946 depth = 1 diff_files = wlroots-meson-build.patch From af5d06593f83344e20537ad5ec7a780eda4fce87 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 24 Nov 2023 10:59:02 +0000 Subject: [PATCH 270/513] cmakelists: fix old wlroots sover --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 95d5a297..3f62a65e 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,7 +62,7 @@ ExternalProject_Add( BUILD_COMMAND ninja -C build BUILD_ALWAYS true BUILD_IN_SOURCE true - BUILD_BYPRODUCTS ${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.12032 + BUILD_BYPRODUCTS ${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.13032 INSTALL_COMMAND echo "wlroots: install not needed" ) @@ -222,7 +222,7 @@ function(protocol protoPath protoName external) endfunction() target_link_libraries(Hyprland - ${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.12032 # wlroots is provided by us + ${CMAKE_SOURCE_DIR}/subprojects/wlroots/build/libwlroots.so.13032 # wlroots is provided by us OpenGL::EGL OpenGL::GL Threads::Threads From 802ab58f8a129b42d61ec13898fd978e0920f7d8 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 24 Nov 2023 12:32:35 +0000 Subject: [PATCH 271/513] renderer: fix inverseOpaque calcs in renderWithBlur --- src/render/OpenGL.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 119d522b..622a211d 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1314,7 +1314,8 @@ void CHyprOpenGLImpl::renderTextureWithBlur(const CTexture& tex, CBox* pBox, flo // amazing hack: the surface has an opaque region! CRegion inverseOpaque; - if (a >= 1.f) { + if (a >= 1.f && std::round(pSurface->current.width * m_RenderData.pMonitor->scale) == pBox->w && + std::round(pSurface->current.height * m_RenderData.pMonitor->scale) == pBox->h) { pixman_box32_t surfbox = {0, 0, pSurface->current.width * pSurface->current.scale, pSurface->current.height * pSurface->current.scale}; inverseOpaque = &pSurface->current.opaque; inverseOpaque.invert(&surfbox).intersect(0, 0, pSurface->current.width * pSurface->current.scale, pSurface->current.height * pSurface->current.scale); From aedcade68dd0615fd919a7249633a554d0accd81 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 24 Nov 2023 12:37:10 +0000 Subject: [PATCH 272/513] opengl: better checking for required introspection performance woo --- src/render/OpenGL.cpp | 46 ++++++++++++++++++++++++++++++++++++++++--- src/render/OpenGL.hpp | 7 ++++--- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 622a211d..638b562f 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -115,10 +115,50 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool return shader; } -void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { - m_RenderData.pMonitor = pMonitor; +bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { + // passes requiring introspection are the ones that need to render blur. static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue; + static auto* const PXRAY = &g_pConfigManager->getConfigValuePtr("decoration:blur:xray")->intValue; + + if (*PBLUR == 0) + return false; + + if (m_RenderData.pCurrentMonData->blurFBShouldRender) + return true; + + if (pMonitor->solitaryClient) + return false; + + for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { + if (ls->forceBlur && !ls->xray) + return true; + } + + if (*PXRAY) + return false; + + for (auto& w : g_pCompositor->m_vWindows) { + if (!w->m_bIsMapped || w->isHidden() || (!w->m_bIsFloating && !g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))) + continue; + + if (!g_pHyprRenderer->shouldRenderWindow(w.get())) + continue; + + if (w->m_sAdditionalConfigData.forceNoBlur.toUnderlying() == true || w->m_sAdditionalConfigData.xray.toUnderlying() == true) + continue; + + if (w->opaque()) + continue; + + return true; + } + + return false; +} + +void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { + m_RenderData.pMonitor = pMonitor; TRACY_GPU_ZONE("RenderBegin"); @@ -163,7 +203,7 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { const auto PRBO = g_pHyprRenderer->getCurrentRBO(); if (m_sFinalScreenShader.program > 0 || m_bFakeFrame || m_RenderData.mouseZoomFactor != 1.0 || pMonitor->vecPixelSize != PRBO->getFB()->m_vSize || - (*PBLUR != 0 && !pMonitor->solitaryClient /* TODO: revisit when possible */)) { + passRequiresIntrospection(pMonitor)) { // we have to offload // bind the primary Hypr Framebuffer m_RenderData.pCurrentMonData->offloadFB.bind(); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 4311e16c..9ff571f2 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -30,8 +30,7 @@ inline const float fullVerts[] = { }; inline const float fanVertsFull[] = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f}; -enum eDiscardMode -{ +enum eDiscardMode { DISCARD_OPAQUE = 1, DISCARD_ALPHA = 1 << 1 }; @@ -173,7 +172,7 @@ class CHyprOpenGLImpl { struct { PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES = nullptr; - PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = nullptr; + PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = nullptr; } m_sProc; private: @@ -209,6 +208,8 @@ class CHyprOpenGLImpl { bool shouldUseNewBlurOptimizations(SLayerSurface* pLayer, CWindow* pWindow); + bool passRequiresIntrospection(CMonitor* pMonitor); + friend class CHyprRenderer; }; From 258c83f3bb08cd5a342f4e437e41df179298b4e1 Mon Sep 17 00:00:00 2001 From: thejch <66577496+thejch@users.noreply.github.com> Date: Fri, 24 Nov 2023 04:42:20 -0800 Subject: [PATCH 273/513] exec: remove redundant environment variables from spawn (#3923) --- src/managers/KeybindManager.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index c3a5efe1..986de55e 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -641,11 +641,6 @@ void CKeybindManager::spawn(std::string args) { args = args.substr(args.find_first_of(']') + 1); } - if (g_pXWaylandManager->m_sWLRXWayland) - args = "WAYLAND_DISPLAY=" + std::string(g_pCompositor->m_szWLDisplaySocket) + " DISPLAY=" + std::string(g_pXWaylandManager->m_sWLRXWayland->display_name) + " " + args; - else - args = "WAYLAND_DISPLAY=" + std::string(g_pCompositor->m_szWLDisplaySocket) + " " + args; - const uint64_t PROC = spawnRaw(args); if (!RULES.empty()) { From f9ba5a0551d2b4581a6b8f20c157d120655c337c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= Date: Fri, 24 Nov 2023 11:58:18 +0000 Subject: [PATCH 274/513] flake.lock: update nixpkgs and xdph --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index d1a8c037..3ec705bf 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1698134075, - "narHash": "sha256-foCD+nuKzfh49bIoiCBur4+Fx1nozo+4C/6k8BYk4sg=", + "lastModified": 1700612854, + "narHash": "sha256-yrQ8osMD+vDLGFX7pcwsY/Qr5PUd6OmDMYJZzZi0+zc=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "8efd5d1e283604f75a808a20e6cde0ef313d07d4", + "rev": "19cbff58383a4ae384dea4d1d0c823d72b49d614", "type": "github" }, "original": { @@ -95,11 +95,11 @@ ] }, "locked": { - "lastModified": 1697981233, - "narHash": "sha256-y8q4XUwx+gVK7i2eLjfR32lVo7TYvEslyzrmzYEaPZU=", + "lastModified": 1700508250, + "narHash": "sha256-X4o/mifI7Nhu0UKYlxx53wIC+gYDo3pVM9L2u3PE2bE=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "22e7a65ff9633e1dedfa5317fdffc49f68de2ff2", + "rev": "eb120ff25265ecacd0fc13d7dab12131b60d0f47", "type": "github" }, "original": { From be3d635265331543b37c6106185fbb67b1293fb3 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 24 Nov 2023 13:08:46 +0000 Subject: [PATCH 275/513] makefile: update wlroots sover --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index dc7f7329..0c0b9d10 100644 --- a/Makefile +++ b/Makefile @@ -50,7 +50,7 @@ install: install -m644 ./docs/*.1 ${PREFIX}/share/man/man1 mkdir -p ${PREFIX}/lib/ - cp ./subprojects/wlroots/build/libwlroots.so.12032 ${PREFIX}/lib/ + cp ./subprojects/wlroots/build/libwlroots.so.13032 ${PREFIX}/lib/ $(MAKE) installheaders @@ -58,7 +58,7 @@ uninstall: rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop rm -f ${PREFIX}/bin/Hyprland rm -f ${PREFIX}/bin/hyprctl - rm -f ${PREFIX}/lib/libwlroots.so.12032 + rm -f ${PREFIX}/lib/libwlroots.so.13032 rm -rf ${PREFIX}/share/hyprland rm -f ${PREFIX}/share/man/man1/Hyprland.1 rm -f ${PREFIX}/share/man/man1/hyprctl.1 From 334d0ae31b9b192b6d8c35a40bc83f9076d22b9d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 24 Nov 2023 13:45:10 +0000 Subject: [PATCH 276/513] monitor: fix transform matrix calculations for transformed fixes #3929 --- src/helpers/Monitor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 833a7a5a..f626bb3d 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -647,7 +647,7 @@ Vector2D CMonitor::middle() { void CMonitor::updateMatrix() { wlr_matrix_identity(projMatrix.data()); if (transform != WL_OUTPUT_TRANSFORM_NORMAL) { - wlr_matrix_translate(projMatrix.data(), vecTransformedSize.x / 2.0, vecTransformedSize.y / 2.0); + wlr_matrix_translate(projMatrix.data(), vecPixelSize.x / 2.0, vecPixelSize.y / 2.0); wlr_matrix_transform(projMatrix.data(), transform); wlr_matrix_translate(projMatrix.data(), -vecTransformedSize.x / 2.0, -vecTransformedSize.y / 2.0); } From d79cf0afe26fd6503a47c17a524d45742bf2461a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 24 Nov 2023 13:47:36 +0000 Subject: [PATCH 277/513] renderer: fix software cursors on nvidia fixes #3926 --- src/render/Renderer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 128f36ef..c39f6f74 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2199,9 +2199,10 @@ void CHyprRenderer::renderSoftwareCursors(CMonitor* pMonitor, const CRegion& dam if (!cursor->texture) continue; - CBox cursorBox = CBox{CURSORPOS.x, CURSORPOS.y, cursor->width, cursor->height}.translate({-cursor->hotspot_x, -cursor->hotspot_y}); + CBox cursorBox = CBox{CURSORPOS.x, CURSORPOS.y, cursor->width, cursor->height}.translate({-cursor->hotspot_x, -cursor->hotspot_y}).scale(pMonitor->scale); - g_pHyprOpenGL->renderTexturePrimitive(cursor->texture, &cursorBox); + // TODO: NVIDIA doesn't like if we use renderTexturePrimitive here. Why? + g_pHyprOpenGL->renderTexture(cursor->texture, &cursorBox, 1.0); } } From 822775aa8c0134e66cbf09b7dfd785fad13f329a Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Fri, 24 Nov 2023 21:18:50 +0000 Subject: [PATCH 278/513] renderer: Fixup double rendering cases with special (#3928) * fixup * better fullscreen --- src/render/Renderer.cpp | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index c39f6f74..00fb6aa1 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -189,6 +189,9 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, CWorksp if (w->m_bIsFullscreen || w->m_bIsFloating) continue; + if (pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID)) + continue; + renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL); } @@ -203,9 +206,16 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, CWorksp if (w->m_bIsFullscreen || !w->m_bIsFloating) continue; + if (w->m_iMonitorID == pWorkspace->m_iMonitorID && pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID)) + continue; + + if (pWorkspace->m_bIsSpecialWorkspace && w->m_iMonitorID != pWorkspace->m_iMonitorID) + continue; // special on another are rendered as a part of the base pass + renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL); } + // TODO: this pass sucks for (auto& w : g_pCompositor->m_vWindows) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID); @@ -217,7 +227,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, CWorksp continue; } - if (w->m_iWorkspaceID == pMonitor->activeWorkspace && !w->m_bIsFullscreen) + if (w->m_iWorkspaceID != pMonitor->activeWorkspace || !w->m_bIsFullscreen) continue; renderWindow(w.get(), pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL, RENDER_PASS_ALL); @@ -236,6 +246,12 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, CWorksp if (w->m_iWorkspaceID != pWorkspaceWindow->m_iWorkspaceID || (!w->m_bCreatedOverFullscreen && !w->m_bPinned) || (!w->m_bIsMapped && !w->m_bFadingOut) || w->m_bIsFullscreen) continue; + if (w->m_iMonitorID == pWorkspace->m_iMonitorID && pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID)) + continue; + + if (pWorkspace->m_bIsSpecialWorkspace && w->m_iMonitorID != pWorkspace->m_iMonitorID) + continue; // special on another are rendered as a part of the base pass + renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL); } } @@ -256,7 +272,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) continue; - if (w->m_iMonitorID == pWorkspace->m_iMonitorID && g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID) && !pWorkspace->m_bIsSpecialWorkspace) + if (pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID)) continue; // render active window after all others of this pass @@ -280,7 +296,7 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork if (w->m_bIsFloating) continue; // floating are in the second pass - if (w->m_iMonitorID == pWorkspace->m_iMonitorID && g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID) && !pWorkspace->m_bIsSpecialWorkspace) + if (pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID)) continue; if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) @@ -301,9 +317,12 @@ void CHyprRenderer::renderWorkspaceWindows(CMonitor* pMonitor, CWorkspace* pWork if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) continue; - if (w->m_iMonitorID == pWorkspace->m_iMonitorID && g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID) && !pWorkspace->m_bIsSpecialWorkspace) + if (w->m_iMonitorID == pWorkspace->m_iMonitorID && pWorkspace->m_bIsSpecialWorkspace != g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID)) continue; + if (pWorkspace->m_bIsSpecialWorkspace && w->m_iMonitorID != pWorkspace->m_iMonitorID) + continue; // special on another are rendered as a part of the base pass + // render the bad boy renderWindow(w.get(), pMonitor, time, true, RENDER_PASS_ALL); } From 1a2a2da6aa1b8ee0ff6b85112d088dcc5c93862f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 24 Nov 2023 21:30:28 +0000 Subject: [PATCH 279/513] renderer: fixup cursor scaling fixes #3935 --- src/render/Renderer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 00fb6aa1..21517703 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2209,7 +2209,7 @@ void CHyprRenderer::recheckSolitaryForMonitor(CMonitor* pMonitor) { } void CHyprRenderer::renderSoftwareCursors(CMonitor* pMonitor, const CRegion& damage, std::optional overridePos) { - const auto CURSORPOS = overridePos.value_or(g_pInputManager->getMouseCoordsInternal() - pMonitor->vecPosition); + const auto CURSORPOS = overridePos.value_or(g_pInputManager->getMouseCoordsInternal() - pMonitor->vecPosition) * pMonitor->scale; wlr_output_cursor* cursor; wl_list_for_each(cursor, &pMonitor->output->cursors, link) { if (!cursor->enabled || !cursor->visible || pMonitor->output->hardware_cursor == cursor) @@ -2218,7 +2218,7 @@ void CHyprRenderer::renderSoftwareCursors(CMonitor* pMonitor, const CRegion& dam if (!cursor->texture) continue; - CBox cursorBox = CBox{CURSORPOS.x, CURSORPOS.y, cursor->width, cursor->height}.translate({-cursor->hotspot_x, -cursor->hotspot_y}).scale(pMonitor->scale); + CBox cursorBox = CBox{CURSORPOS.x, CURSORPOS.y, cursor->width, cursor->height}.translate({-cursor->hotspot_x, -cursor->hotspot_y}); // TODO: NVIDIA doesn't like if we use renderTexturePrimitive here. Why? g_pHyprOpenGL->renderTexture(cursor->texture, &cursorBox, 1.0); From 745b998587fc39db6e3f77caa54074da618cd509 Mon Sep 17 00:00:00 2001 From: Xavier Date: Fri, 24 Nov 2023 22:45:59 +0100 Subject: [PATCH 280/513] renderer: Adding an option to disable first launch animation (#3933) --- src/config/ConfigManager.cpp | 3 ++- src/render/Renderer.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 9f739ce0..63aaa751 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -209,7 +209,8 @@ void CConfigManager::setDefaultVars() { configValues["master:smart_resizing"].intValue = 1; configValues["master:drop_at_cursor"].intValue = 1; - configValues["animations:enabled"].intValue = 1; + configValues["animations:enabled"].intValue = 1; + configValues["animations:first_launch_animation"].intValue = 1; configValues["input:follow_mouse"].intValue = 1; configValues["input:mouse_refocus"].intValue = 1; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 21517703..bc71978b 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -877,6 +877,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { static auto* const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue; static auto* const PBACKGROUNDCOLOR = &g_pConfigManager->getConfigValuePtr("misc:background_color")->intValue; static auto* const PANIMENABLED = &g_pConfigManager->getConfigValuePtr("animations:enabled")->intValue; + static auto* const PFIRSTLAUNCHANIM = &g_pConfigManager->getConfigValuePtr("animations:first_launch_animation")->intValue; static auto* const PTEARINGENABLED = &g_pConfigManager->getConfigValuePtr("general:allow_tearing")->intValue; static int damageBlinkCleanup = 0; // because double-buffered @@ -885,7 +886,7 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { damageBlinkCleanup = 0; static bool firstLaunch = true; - static bool firstLaunchAnimActive = true; + static bool firstLaunchAnimActive = *PFIRSTLAUNCHANIM; float zoomInFactorFirstLaunch = 1.f; From a6eba919356b08a2a403a52c1e5e020734411668 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 25 Nov 2023 00:47:51 +0000 Subject: [PATCH 281/513] opengl: require introspection on mirroring fixes #3939 --- src/render/OpenGL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 638b562f..486531b7 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -202,7 +202,7 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { const auto PRBO = g_pHyprRenderer->getCurrentRBO(); - if (m_sFinalScreenShader.program > 0 || m_bFakeFrame || m_RenderData.mouseZoomFactor != 1.0 || pMonitor->vecPixelSize != PRBO->getFB()->m_vSize || + if (m_sFinalScreenShader.program > 0 || m_bFakeFrame || m_RenderData.mouseZoomFactor != 1.0 || pMonitor->vecPixelSize != PRBO->getFB()->m_vSize || !pMonitor->mirrors.empty() || passRequiresIntrospection(pMonitor)) { // we have to offload // bind the primary Hypr Framebuffer From 512a59731b2e579b66325d0e9ce770919eecd685 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 25 Nov 2023 01:45:04 +0000 Subject: [PATCH 282/513] config: default special_scale_factor to 1 --- src/config/ConfigManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 63aaa751..54ecadb5 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -189,7 +189,7 @@ void CConfigManager::setDefaultVars() { configValues["dwindle:force_split"].intValue = 0; configValues["dwindle:permanent_direction_override"].intValue = 0; configValues["dwindle:preserve_split"].intValue = 0; - configValues["dwindle:special_scale_factor"].floatValue = 0.8f; + configValues["dwindle:special_scale_factor"].floatValue = 1.f; configValues["dwindle:split_width_multiplier"].floatValue = 1.0f; configValues["dwindle:no_gaps_when_only"].intValue = 0; configValues["dwindle:use_active_for_splits"].intValue = 1; @@ -197,7 +197,7 @@ void CConfigManager::setDefaultVars() { configValues["dwindle:smart_split"].intValue = 0; configValues["dwindle:smart_resizing"].intValue = 1; - configValues["master:special_scale_factor"].floatValue = 0.8f; + configValues["master:special_scale_factor"].floatValue = 1.f; configValues["master:mfact"].floatValue = 0.55f; configValues["master:new_is_master"].intValue = 1; configValues["master:always_center_master"].intValue = 0; From 929c44e361fe5cc535a9226b05fba21a0e317d69 Mon Sep 17 00:00:00 2001 From: Junxuan Liao <70618504+MikeWalrus@users.noreply.github.com> Date: Sat, 25 Nov 2023 22:27:57 +0800 Subject: [PATCH 283/513] input: pass mouse input to IME popups (#3922) --- src/Compositor.cpp | 15 +++++++++++++++ src/Compositor.hpp | 1 + src/managers/input/InputManager.cpp | 15 ++++++++++++--- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 42b620fe..b0e1fcb3 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1106,6 +1106,21 @@ wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector< return nullptr; } +SIMEPopup* CCompositor::vectorToIMEPopup(const Vector2D& pos, std::list& popups) { + for (auto& popup : popups) { + auto surface = popup.pSurface->surface; + CBox box{ + popup.realX, + popup.realY, + surface->current.width, + surface->current.height, + }; + if (box.containsPoint(pos)) + return &popup; + } + return nullptr; +} + CWindow* CCompositor::getWindowFromSurface(wlr_surface* pSurface) { for (auto& w : m_vWindows) { if (!w->m_bIsMapped || w->m_bFadingOut || !w->m_bMappedX11) diff --git a/src/Compositor.hpp b/src/Compositor.hpp index d39725aa..8ca43d84 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -139,6 +139,7 @@ class CCompositor { CWindow* vectorToWindowIdeal(const Vector2D&, CWindow* pIgnoreWindow = nullptr); // used only for finding a window to focus on, basically a "findFocusableWindow" CWindow* vectorToWindowTiled(const Vector2D&); wlr_surface* vectorToLayerSurface(const Vector2D&, std::vector>*, Vector2D*, SLayerSurface**); + SIMEPopup* vectorToIMEPopup(const Vector2D& pos, std::list& popups); wlr_surface* vectorWindowToSurface(const Vector2D&, CWindow*, Vector2D& sl); Vector2D vectorToSurfaceLocal(const Vector2D&, CWindow*, wlr_surface*); CWindow* windowFromCursor(); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 2dba7515..058429c9 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -233,10 +233,20 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { surfacePos = PMONITOR->vecPosition; } - // overlay is above fullscreen + // overlays are above fullscreen if (!foundSurface) foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], &surfaceCoords, &pFoundLayerSurface); + // also IME popups + if (!foundSurface) { + auto popup = g_pCompositor->vectorToIMEPopup(mouseCoords, m_sIMERelay.m_lIMEPopups); + if (popup) { + foundSurface = popup->pSurface->surface; + surfacePos = Vector2D(popup->realX, popup->realY); + } + } + + // also top layers if (!foundSurface) foundSurface = g_pCompositor->vectorToLayerSurface(mouseCoords, &PMONITOR->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], &surfaceCoords, &pFoundLayerSurface); @@ -471,7 +481,6 @@ void CInputManager::onMouseButton(wlr_pointer_button_event* e) { } void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_event* e) { - if (!e->surface) g_pHyprRenderer->m_bWindowRequestedCursorHide = true; else @@ -1636,7 +1645,7 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) { CBox box = w->getWindowMainSurfaceBox(); eBorderIconDirection direction = BORDERICON_NONE; CBox boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE), - box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; + box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; if (w->hasPopupAt(mouseCoords)) direction = BORDERICON_NONE; From de95e956a0dc9d837cde8eb714a7fd3fa5e47673 Mon Sep 17 00:00:00 2001 From: coldified <139003835+coldified@users.noreply.github.com> Date: Sat, 25 Nov 2023 23:32:01 +0900 Subject: [PATCH 284/513] meson: Update wlroots-meson-build.patch (#3950) --- subprojects/packagefiles/wlroots-meson-build.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/packagefiles/wlroots-meson-build.patch b/subprojects/packagefiles/wlroots-meson-build.patch index 6741fdc7..fd6f84db 100644 --- a/subprojects/packagefiles/wlroots-meson-build.patch +++ b/subprojects/packagefiles/wlroots-meson-build.patch @@ -38,8 +38,8 @@ index 29b103a..0b6e5a4 100644 # necessary for bugfix releases. Increasing soversion is required because # wlroots never guarantees ABI stability -- only API stability is guaranteed # between minor releases. --soversion = 12 -+soversion = 12032 +-soversion = 13 ++soversion = 13032 little_endian = target_machine.endian() == 'little' big_endian = target_machine.endian() == 'big' From 2ce4b94a22242ae77f6a2899d389dcb56d0e5fa8 Mon Sep 17 00:00:00 2001 From: Jibin George Date: Sat, 25 Nov 2023 20:09:21 +0530 Subject: [PATCH 285/513] input: Fix custom acceleration profile config (#3948) --- src/managers/input/InputManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 058429c9..be5d296e 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1074,7 +1074,7 @@ void CInputManager::setPointerConfigs() { const auto CONFIG = libinput_config_accel_create(LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM); libinput_config_accel_set_points(CONFIG, LIBINPUT_ACCEL_TYPE_MOTION, step, points.size(), points.data()); - libinput_device_config_accel_set_profile(LIBINPUTDEV, LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM); + libinput_device_config_accel_apply(LIBINPUTDEV, CONFIG); libinput_config_accel_destroy(CONFIG); } catch (std::exception& e) { Debug::log(ERR, "Invalid values in custom accel profile"); } } else { From 3fe6162af1904f15fc5526c179c06a48265bdbff Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 25 Nov 2023 14:52:47 +0000 Subject: [PATCH 286/513] opengl: fix xray modes in introspection checks for ls fixes #3953 --- src/render/OpenGL.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 486531b7..a20c94ca 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -130,8 +130,15 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { if (pMonitor->solitaryClient) return false; + for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]) { + const auto XRAYMODE = ls->xray == -1 ? *PXRAY : ls->xray; + if (ls->forceBlur && !XRAYMODE) + return true; + } + for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]) { - if (ls->forceBlur && !ls->xray) + const auto XRAYMODE = ls->xray == -1 ? *PXRAY : ls->xray; + if (ls->forceBlur && !XRAYMODE) return true; } From 6f733292bf2dae2adf1e7524546e140a93824033 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 25 Nov 2023 17:45:08 +0000 Subject: [PATCH 287/513] renderer: nvidia checks and use glFinish on nvidia fixes #3952 #3946 --- CMakeLists.txt | 1 - src/render/Renderer.cpp | 49 ++++++++++++++++++++++++++++++++++++++++- src/render/Renderer.hpp | 3 +++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f62a65e..6f52c554 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,7 +99,6 @@ set(CMAKE_ENABLE_EXPORTS TRUE) message(STATUS "Checking deps...") find_package(Threads REQUIRED) - find_package(PkgConfig REQUIRED) find_package(OpenGL REQUIRED) pkg_check_modules(deps REQUIRED IMPORTED_TARGET wayland-server wayland-client wayland-cursor wayland-protocols cairo libdrm xkbcommon libinput pango pangocairo pixman-1) # we do not check for wlroots, as we provide it ourselves diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index bc71978b..273bc1ca 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -4,11 +4,51 @@ #include "../helpers/Region.hpp" #include +extern "C" { +#include +} + CHyprRenderer::CHyprRenderer() { const auto ENV = getenv("WLR_DRM_NO_ATOMIC"); if (ENV && std::string(ENV) == "1") m_bTearingEnvSatisfied = true; + + if (g_pCompositor->m_sWLRSession) { + wlr_device* dev; + wl_list_for_each(dev, &g_pCompositor->m_sWLRSession->devices, link) { + const auto DRMV = drmGetVersion(dev->fd); + + std::string name = std::string{DRMV->name, DRMV->name_len}; + std::transform(name.begin(), name.end(), name.begin(), tolower); + + if (name.contains("nvidia")) + m_bNvidia = true; + + Debug::log(LOG, "DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel, + std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len}); + + drmFreeVersion(DRMV); + } + } else { + Debug::log(LOG, "m_sWLRSession is null, omitting full DRM node checks"); + + const auto DRMV = drmGetVersion(g_pCompositor->m_iDRMFD); + + std::string name = std::string{DRMV->name, DRMV->name_len}; + std::transform(name.begin(), name.end(), name.begin(), tolower); + + if (name.contains("nvidia")) + m_bNvidia = true; + + Debug::log(LOG, "Primary DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel, + std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len}); + + drmFreeVersion(DRMV); + } + + if (m_bNvidia) + Debug::log(WARN, "NVIDIA detected, please remember to follow nvidia instructions on the wiki"); } void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { @@ -2284,7 +2324,10 @@ void CHyprRenderer::endRender() { return; } - glFlush(); + if (isNvidia()) + glFinish(); + else + glFlush(); if (m_eRenderMode == RENDER_MODE_NORMAL) wlr_output_state_set_buffer(&PMONITOR->output->pending, m_pCurrentWlrBuffer); @@ -2304,4 +2347,8 @@ void CHyprRenderer::onRenderbufferDestroy(CRenderbuffer* rb) { CRenderbuffer* CHyprRenderer::getCurrentRBO() { return m_pCurrentRenderbuffer; +} + +bool CHyprRenderer::isNvidia() { + return m_bNvidia; } \ No newline at end of file diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 6b4f0561..1107d993 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -69,6 +69,7 @@ class CHyprRenderer { void renderSoftwareCursors(CMonitor* pMonitor, const CRegion& damage, std::optional overridePos = {}); void onRenderbufferDestroy(CRenderbuffer* rb); CRenderbuffer* getCurrentRBO(); + bool isNvidia(); bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, wlr_buffer* withBuffer = nullptr); void endRender(); @@ -121,6 +122,8 @@ class CHyprRenderer { eRenderMode m_eRenderMode = RENDER_MODE_NORMAL; int m_iLastBufferAge = 0; + bool m_bNvidia = false; + CRenderbuffer* getOrCreateRenderbuffer(wlr_buffer* buffer, uint32_t fmt); std::vector> m_vRenderbuffers; From 15b282ee0c8b48724b7d068aa95bb1133fdda2d7 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 25 Nov 2023 17:46:50 +0000 Subject: [PATCH 288/513] opengl: fix window introspection check --- src/render/OpenGL.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index a20c94ca..f2028aaf 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -118,8 +118,9 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { // passes requiring introspection are the ones that need to render blur. - static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue; - static auto* const PXRAY = &g_pConfigManager->getConfigValuePtr("decoration:blur:xray")->intValue; + static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue; + static auto* const PXRAY = &g_pConfigManager->getConfigValuePtr("decoration:blur:xray")->intValue; + static auto* const POPTIM = &g_pConfigManager->getConfigValuePtr("decoration:blur:new_optimizations")->intValue; if (*PBLUR == 0) return false; @@ -146,7 +147,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { return false; for (auto& w : g_pCompositor->m_vWindows) { - if (!w->m_bIsMapped || w->isHidden() || (!w->m_bIsFloating && !g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))) + if (!w->m_bIsMapped || w->isHidden() || (!w->m_bIsFloating && *POPTIM)) continue; if (!g_pHyprRenderer->shouldRenderWindow(w.get())) From b281d8647a557f51977c25cb6c0d2f818fe4e4e4 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 25 Nov 2023 17:56:38 +0000 Subject: [PATCH 289/513] screencopy: use new isNvidia() for format --- src/protocols/Screencopy.cpp | 2 +- src/protocols/ToplevelExport.cpp | 2 +- src/render/Renderer.cpp | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index cff84fc5..f0f0f69e 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -210,7 +210,7 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r PFRAME->client = PCLIENT; PCLIENT->ref++; - PFRAME->shmFormat = wlr_output_preferred_read_format(PFRAME->pMonitor->output); + PFRAME->shmFormat = g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XRGB8888 : wlr_output_preferred_read_format(PFRAME->pMonitor->output); if (PFRAME->shmFormat == DRM_FORMAT_INVALID) { Debug::log(ERR, "No format supported by renderer in capture output"); zwlr_screencopy_frame_v1_send_failed(PFRAME->resource); diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index db602396..6c626e87 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -177,7 +177,7 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou const auto PMONITOR = g_pCompositor->getMonitorFromID(PFRAME->pWindow->m_iMonitorID); - PFRAME->shmFormat = wlr_output_preferred_read_format(PMONITOR->output); + PFRAME->shmFormat = g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XRGB8888 : wlr_output_preferred_read_format(PMONITOR->output); if (PFRAME->shmFormat == DRM_FORMAT_INVALID) { Debug::log(ERR, "No format supported by renderer in capture toplevel"); hyprland_toplevel_export_frame_v1_send_failed(resource); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 273bc1ca..bdf683e9 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -16,7 +16,7 @@ CHyprRenderer::CHyprRenderer() { if (g_pCompositor->m_sWLRSession) { wlr_device* dev; - wl_list_for_each(dev, &g_pCompositor->m_sWLRSession->devices, link) { + wl_list_for_each(dev, &g_pCompositor->m_sWLRSession->devices, link) { const auto DRMV = drmGetVersion(dev->fd); std::string name = std::string{DRMV->name, DRMV->name_len}; @@ -26,7 +26,7 @@ CHyprRenderer::CHyprRenderer() { m_bNvidia = true; Debug::log(LOG, "DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel, - std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len}); + std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len}); drmFreeVersion(DRMV); } @@ -42,7 +42,7 @@ CHyprRenderer::CHyprRenderer() { m_bNvidia = true; Debug::log(LOG, "Primary DRM driver information: {} v{}.{}.{} from {} description {}", name, DRMV->version_major, DRMV->version_minor, DRMV->version_patchlevel, - std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len}); + std::string{DRMV->date, DRMV->date_len}, std::string{DRMV->desc, DRMV->desc_len}); drmFreeVersion(DRMV); } From a5f64b48ca23edfba807c8842ff12e3d96494f5f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 25 Nov 2023 19:24:59 +0000 Subject: [PATCH 290/513] deps: downgrade wlroots to fix crashes --- subprojects/wlroots | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/wlroots b/subprojects/wlroots index f1762f42..2eb22523 160000 --- a/subprojects/wlroots +++ b/subprojects/wlroots @@ -1 +1 @@ -Subproject commit f1762f428b0ef2989c81f57ea9e810403d34d946 +Subproject commit 2eb225236eb72f27beec921e9f37ddf58e874fba From 98c7ba4782476c10e5854a7e520c47bb10353607 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 25 Nov 2023 19:25:44 +0000 Subject: [PATCH 291/513] [gha] Nix: update wlroots --- flake.lock | 8 ++++---- flake.nix | 2 +- subprojects/wlroots.wrap | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 3ec705bf..4b31bc1a 100644 --- a/flake.lock +++ b/flake.lock @@ -67,18 +67,18 @@ "flake": false, "locked": { "host": "gitlab.freedesktop.org", - "lastModified": 1700736101, - "narHash": "sha256-1Fh1xf/JX5zFbGIF9LDaffaleG6JDwwwnKby0LyiXEA=", + "lastModified": 1700734054, + "narHash": "sha256-SBu1y01WjCSrcCKvgfCDDckrZjU/OmCJT8Xc+hPow7E=", "owner": "wlroots", "repo": "wlroots", - "rev": "f1762f428b0ef2989c81f57ea9e810403d34d946", + "rev": "2eb225236eb72f27beec921e9f37ddf58e874fba", "type": "gitlab" }, "original": { "host": "gitlab.freedesktop.org", "owner": "wlroots", "repo": "wlroots", - "rev": "f1762f428b0ef2989c81f57ea9e810403d34d946", + "rev": "2eb225236eb72f27beec921e9f37ddf58e874fba", "type": "gitlab" } }, diff --git a/flake.nix b/flake.nix index 716648be..6c5387c3 100644 --- a/flake.nix +++ b/flake.nix @@ -12,7 +12,7 @@ host = "gitlab.freedesktop.org"; owner = "wlroots"; repo = "wlroots"; - rev = "f1762f428b0ef2989c81f57ea9e810403d34d946"; + rev = "2eb225236eb72f27beec921e9f37ddf58e874fba"; flake = false; }; diff --git a/subprojects/wlroots.wrap b/subprojects/wlroots.wrap index 94757838..7fb801b0 100644 --- a/subprojects/wlroots.wrap +++ b/subprojects/wlroots.wrap @@ -1,7 +1,7 @@ [wrap-git] directory = wlroots url = https://gitlab.freedesktop.org/wlroots/wlroots.git -revision = f1762f428b0ef2989c81f57ea9e810403d34d946 +revision = 2eb225236eb72f27beec921e9f37ddf58e874fba depth = 1 diff_files = wlroots-meson-build.patch From ad3f6886484e9adbab532de125e69a70c54fa13e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 25 Nov 2023 19:40:15 +0000 Subject: [PATCH 292/513] opengl: check for introspection on special_blur --- src/render/OpenGL.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index f2028aaf..f2cec5df 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -118,9 +118,10 @@ GLuint CHyprOpenGLImpl::compileShader(const GLuint& type, std::string src, bool bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { // passes requiring introspection are the ones that need to render blur. - static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue; - static auto* const PXRAY = &g_pConfigManager->getConfigValuePtr("decoration:blur:xray")->intValue; - static auto* const POPTIM = &g_pConfigManager->getConfigValuePtr("decoration:blur:new_optimizations")->intValue; + static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue; + static auto* const PXRAY = &g_pConfigManager->getConfigValuePtr("decoration:blur:xray")->intValue; + static auto* const POPTIM = &g_pConfigManager->getConfigValuePtr("decoration:blur:new_optimizations")->intValue; + static auto* const PBLURSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:blur:special")->intValue; if (*PBLUR == 0) return false; @@ -143,6 +144,18 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { return true; } + if (*PBLURSPECIAL) { + for (auto& ws : g_pCompositor->m_vWorkspaces) { + if (!ws->m_bIsSpecialWorkspace || ws->m_iMonitorID != pMonitor->ID) + continue; + + if (ws->m_fAlpha.fl() == 0) + continue; + + return true; + } + } + if (*PXRAY) return false; From cd96ceecc551c25631783499bd92c6662c5d3616 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sun, 26 Nov 2023 02:58:57 +0000 Subject: [PATCH 293/513] build: remove nv patches (#3957) --- .github/workflows/nix-build.yml | 1 - flake.nix | 1 - nix/default.nix | 9 +++---- nix/hm-module.nix | 9 +++---- nix/module.nix | 16 ++++++------- nix/overlays.nix | 7 +++++- nix/patches/wlroots-nvidia.patch | 41 -------------------------------- nix/wlroots.nix | 10 +------- 8 files changed, 22 insertions(+), 72 deletions(-) delete mode 100644 nix/patches/wlroots-nvidia.patch diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index fb98f099..a1ea0f24 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -10,7 +10,6 @@ jobs: matrix: package: - hyprland - - hyprland-nvidia - xdg-desktop-portal-hyprland runs-on: ubuntu-latest diff --git a/flake.nix b/flake.nix index 6c5387c3..58f45c58 100644 --- a/flake.nix +++ b/flake.nix @@ -65,7 +65,6 @@ hyprland hyprland-unwrapped hyprland-debug - hyprland-nvidia # hyprland-extras xdg-desktop-portal-hyprland # dependencies diff --git a/nix/default.nix b/nix/default.nix index 63ef838e..42808a5f 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -27,7 +27,6 @@ xcbutilwm, xwayland, debug ? false, - enableNvidiaPatches ? false, enableXWayland ? true, legacyRenderer ? false, withSystemd ? lib.meta.availableOn stdenv.hostPlatform systemd, @@ -35,13 +34,15 @@ version ? "git", commit, # deprecated flags + enableNvidiaPatches ? false, nvidiaPatches ? false, hidpiXWayland ? false, }: -assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been renamed `enableNvidiaPatches`"; +assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed."; +assert lib.assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed."; assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland"; stdenv.mkDerivation { - pname = "hyprland${lib.optionalString enableNvidiaPatches "-nvidia"}${lib.optionalString debug "-debug"}"; + pname = "hyprland${lib.optionalString debug "-debug"}"; inherit version; src = lib.cleanSourceWith { @@ -82,7 +83,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov wayland wayland-protocols pciutils - (wlroots.override {inherit enableNvidiaPatches;}) + wlroots ] ++ lib.optionals enableXWayland [libxcb xcbutilwm xwayland] ++ lib.optionals withSystemd [systemd]; diff --git a/nix/hm-module.nix b/nix/hm-module.nix index 123bceb3..9b065e6f 100644 --- a/nix/hm-module.nix +++ b/nix/hm-module.nix @@ -7,7 +7,6 @@ self: { cfg = config.wayland.windowManager.hyprland; defaultHyprlandPackage = self.packages.${pkgs.stdenv.hostPlatform.system}.default.override { enableXWayland = cfg.xwayland.enable; - inherit (cfg) enableNvidiaPatches; }; in { disabledModules = ["services/window-managers/hyprland.nix"]; @@ -35,12 +34,10 @@ in { defaultText = lib.literalExpression '' hyprland.packages.''${pkgs.stdenv.hostPlatform.system}.default.override { enableXWayland = config.wayland.windowManager.hyprland.xwayland.enable; - inherit (config.wayland.windowManager.hyprland) enableNvidiaPatches; } ''; description = lib.mdDoc '' - Hyprland package to use. Will override the 'xwayland' and - 'enableNvidiaPatches' options. + Hyprland package to use. Will override the 'xwayland' option. Defaults to the one provided by the flake. Set it to {package}`pkgs.hyprland` to use the one provided by nixpkgs or @@ -86,8 +83,6 @@ in { xwayland.enable = lib.mkEnableOption (lib.mdDoc "XWayland") // {default = true;}; - enableNvidiaPatches = lib.mkEnableOption (lib.mdDoc "patching wlroots for better Nvidia support."); - extraConfig = lib.mkOption { type = lib.types.nullOr lib.types.lines; default = ""; @@ -173,5 +168,7 @@ in { imports = [ (lib.mkRemovedOptionModule ["wayland" "windowManager" "hyprland" "xwayland" "hidpi"] "Support for this option has been removed. Refer to https://wiki.hyprland.org/Configuring/XWayland for more info") + (lib.mkRemovedOptionModule ["wayland" "windowManager" "hyprland" "xwayland" "enableNvidiaPatches"] + "Nvidia patches are no longer needed for Hyprland") ]; } diff --git a/nix/module.nix b/nix/module.nix index fcb29837..1f1d2585 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -37,7 +37,6 @@ in { readOnly = true; default = cfg.package.override { enableXWayland = cfg.xwayland.enable; - enableNvidiaPatches = cfg.enableNvidiaPatches; }; defaultText = literalExpression @@ -50,12 +49,6 @@ in { portalPackage = mkPackageOptionMD inputs.xdph.packages.${system} "xdg-desktop-portal-hyprland" {}; xwayland.enable = mkEnableOption (mdDoc "support for XWayland") // {default = true;}; - - enableNvidiaPatches = - mkEnableOption null - // { - description = mdDoc "Whether to apply patches to wlroots for better Nvidia support."; - }; }; config = mkIf cfg.enable { @@ -91,9 +84,14 @@ in { "XWayland patches are deprecated. Refer to https://wiki.hyprland.org/Configuring/XWayland" ) ( - mkRenamedOptionModule - ["programs" "hyprland" "nvidiaPatches"] + mkRemovedOptionModule ["programs" "hyprland" "enableNvidiaPatches"] + "Nvidia patches are no longer needed" + ) + ( + mkRemovedOptionModule + ["programs" "hyprland" "nvidiaPatches"] + "Nvidia patches are no longer needed" ) ]; } diff --git a/nix/overlays.nix b/nix/overlays.nix index 3c38d740..9ad623fe 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -38,7 +38,12 @@ in { }; hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;}; hyprland-debug = final.hyprland.override {debug = true;}; - hyprland-nvidia = final.hyprland.override {enableNvidiaPatches = true;}; + hyprland-nvidia = + builtins.trace '' + hyprland-nvidia was removed. Please use the hyprland package. + Nvidia patches are no longer needed. + '' + final.hyprland; hyprland-hidpi = builtins.trace '' hyprland-hidpi was removed. Please use the hyprland package. diff --git a/nix/patches/wlroots-nvidia.patch b/nix/patches/wlroots-nvidia.patch deleted file mode 100644 index 01bdd342..00000000 --- a/nix/patches/wlroots-nvidia.patch +++ /dev/null @@ -1,41 +0,0 @@ -diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c -index 9fe934f7..9662d4ee 100644 ---- a/render/gles2/renderer.c -+++ b/render/gles2/renderer.c -@@ -176,7 +176,7 @@ static bool gles2_bind_buffer(struct wlr_renderer *wlr_renderer, - assert(wlr_egl_is_current(renderer->egl)); - - push_gles2_debug(renderer); -- glFlush(); -+ glFinish(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - pop_gles2_debug(renderer); - -diff --git a/types/output/render.c b/types/output/render.c -index 2e38919a..97f78608 100644 ---- a/types/output/render.c -+++ b/types/output/render.c -@@ -240,22 +240,7 @@ bool output_pick_format(struct wlr_output *output, - } - - uint32_t wlr_output_preferred_read_format(struct wlr_output *output) { -- struct wlr_renderer *renderer = output->renderer; -- assert(renderer != NULL); -- -- if (!renderer->impl->preferred_read_format || !renderer->impl->read_pixels) { -- return DRM_FORMAT_INVALID; -- } -- -- if (!wlr_output_attach_render(output, NULL)) { -- return false; -- } -- -- uint32_t fmt = renderer->impl->preferred_read_format(renderer); -- -- output_clear_back_buffer(output); -- -- return fmt; -+ return DRM_FORMAT_XRGB8888; - } - - struct wlr_render_pass *wlr_output_begin_render_pass(struct wlr_output *output, diff --git a/nix/wlroots.nix b/nix/wlroots.nix index c1aa27de..f48ba35c 100644 --- a/nix/wlroots.nix +++ b/nix/wlroots.nix @@ -1,5 +1,4 @@ { - lib, version, src, wlroots, @@ -7,18 +6,11 @@ libdisplay-info, libliftoff, enableXWayland ? true, - enableNvidiaPatches ? false, }: wlroots.overrideAttrs (old: { inherit version src enableXWayland; - pname = "${old.pname}-hyprland${lib.optionalString enableNvidiaPatches "-nvidia"}"; - - patches = - (old.patches or []) - ++ (lib.optionals enableNvidiaPatches [ - ./patches/wlroots-nvidia.patch - ]); + pname = "${old.pname}-hyprland"; buildInputs = old.buildInputs ++ [hwdata libliftoff libdisplay-info]; From 9e2b939024448d64df6af1f5d2ea5ceee078a539 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 26 Nov 2023 14:53:22 +0000 Subject: [PATCH 294/513] surface: avoid infinite pointer image resets fixes #3729, should also #3968 --- src/helpers/WLSurface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/WLSurface.cpp b/src/helpers/WLSurface.cpp index 256c89b8..3528a72d 100644 --- a/src/helpers/WLSurface.cpp +++ b/src/helpers/WLSurface.cpp @@ -65,7 +65,7 @@ void CWLSurface::destroy() { if (g_pInputManager->m_pLastMouseSurface == m_pWLRSurface) g_pInputManager->m_pLastMouseSurface = nullptr; if (g_pHyprRenderer->m_sLastCursorData.surf == m_pWLRSurface) - g_pInputManager->setCursorImageOverride("left_ptr"); + g_pHyprRenderer->m_sLastCursorData.surf.reset(); m_pWLRSurface = nullptr; From 75e579931088671fb333efd2a3923ff96b868fe9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 26 Nov 2023 14:54:34 +0000 Subject: [PATCH 295/513] layer-shell: simulate mouse movement on unmap --- src/events/Layers.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/events/Layers.cpp b/src/events/Layers.cpp index 5f295408..a9d8b5d0 100644 --- a/src/events/Layers.cpp +++ b/src/events/Layers.cpp @@ -254,6 +254,8 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) { geomFixed = {layersurface->geometry.x + (int)PMONITOR->vecPosition.x, layersurface->geometry.y + (int)PMONITOR->vecPosition.y, (int)layersurface->layerSurface->surface->current.width, (int)layersurface->layerSurface->surface->current.height}; g_pHyprRenderer->damageBox(&geomFixed); + + g_pInputManager->simulateMouseMovement(); } void Events::listener_commitLayerSurface(void* owner, void* data) { From 408d96668d57fdd1a713e56f1d40a9befd51bd4a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 26 Nov 2023 15:06:42 +0000 Subject: [PATCH 296/513] renderer: use occlusion checks for buffer clear --- src/render/OpenGL.hpp | 3 ++- src/render/Renderer.cpp | 28 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 9ff571f2..ea2fe07e 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -30,7 +30,8 @@ inline const float fullVerts[] = { }; inline const float fanVertsFull[] = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f}; -enum eDiscardMode { +enum eDiscardMode +{ DISCARD_OPAQUE = 1, DISCARD_ALPHA = 1 << 1 }; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index bdf683e9..770ca16a 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -650,9 +650,11 @@ void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, CMon } void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* time, const Vector2D& translate, const float& scale) { - static auto* const PDIMSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:dim_special")->floatValue; - static auto* const PBLURSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:blur:special")->intValue; - static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue; + static auto* const PDIMSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:dim_special")->floatValue; + static auto* const PBLURSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:blur:special")->intValue; + static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue; + static auto* const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue; + static auto* const PBACKGROUNDCOLOR = &g_pConfigManager->getConfigValuePtr("misc:background_color")->intValue; const SRenderModifData RENDERMODIFDATA = {translate, scale}; @@ -684,6 +686,15 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* if (!g_pHyprOpenGL->m_RenderData.pCurrentMonData->blurFBShouldRender) setOccludedForBackLayers(g_pHyprOpenGL->m_RenderData.damage, pWorkspace); + g_pHyprOpenGL->blend(false); + if (!canSkipBackBufferClear(pMonitor)) { + if (*PRENDERTEX /* inverted cfg flag */) + g_pHyprOpenGL->clear(CColor(*PBACKGROUNDCOLOR)); + else + g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper" + } + g_pHyprOpenGL->blend(true); + for (auto& ls : pMonitor->m_aLayerSurfaceLayers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]) { renderLayer(ls.get(), pMonitor, time); } @@ -914,8 +925,6 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { static auto* const PNODIRECTSCANOUT = &g_pConfigManager->getConfigValuePtr("misc:no_direct_scanout")->intValue; static auto* const PVFR = &g_pConfigManager->getConfigValuePtr("misc:vfr")->intValue; static auto* const PZOOMFACTOR = &g_pConfigManager->getConfigValuePtr("misc:cursor_zoom_factor")->floatValue; - static auto* const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue; - static auto* const PBACKGROUNDCOLOR = &g_pConfigManager->getConfigValuePtr("misc:background_color")->intValue; static auto* const PANIMENABLED = &g_pConfigManager->getConfigValuePtr("animations:enabled")->intValue; static auto* const PFIRSTLAUNCHANIM = &g_pConfigManager->getConfigValuePtr("animations:first_launch_animation")->intValue; static auto* const PTEARINGENABLED = &g_pConfigManager->getConfigValuePtr("general:allow_tearing")->intValue; @@ -1144,15 +1153,6 @@ void CHyprRenderer::renderMonitor(CMonitor* pMonitor) { EMIT_HOOK_EVENT("render", RENDER_POST_MIRROR); renderCursor = false; } else { - g_pHyprOpenGL->blend(false); - if (!canSkipBackBufferClear(pMonitor)) { - if (*PRENDERTEX /* inverted cfg flag */) - g_pHyprOpenGL->clear(CColor(*PBACKGROUNDCOLOR)); - else - g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper" - } - g_pHyprOpenGL->blend(true); - CBox renderBox = {0, 0, (int)pMonitor->vecPixelSize.x, (int)pMonitor->vecPixelSize.y}; renderWorkspace(pMonitor, g_pCompositor->getWorkspaceByID(pMonitor->activeWorkspace), &now, renderBox); From 68e57b7ee36f015d99988f38cb3a8b83c23ae7c3 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 26 Nov 2023 15:24:24 +0000 Subject: [PATCH 297/513] renderer: proper full occlusion checks for back layer --- src/helpers/Region.cpp | 5 +++++ src/helpers/Region.hpp | 1 + src/render/Renderer.cpp | 7 ++++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/helpers/Region.cpp b/src/helpers/Region.cpp index df7de442..8f180416 100644 --- a/src/helpers/Region.cpp +++ b/src/helpers/Region.cpp @@ -88,6 +88,11 @@ CRegion& CRegion::invert(pixman_box32_t* box) { return *this; } +CRegion& CRegion::invert(const CBox& box) { + pixman_box32 pixmanBox = {box.x, box.y, box.w + box.x, box.h + box.y}; + return this->invert(&pixmanBox); +} + CRegion& CRegion::translate(const Vector2D& vec) { pixman_region32_translate(&m_rRegion, vec.x, vec.y); return *this; diff --git a/src/helpers/Region.hpp b/src/helpers/Region.hpp index 7554aa58..972a2ba7 100644 --- a/src/helpers/Region.hpp +++ b/src/helpers/Region.hpp @@ -47,6 +47,7 @@ class CRegion { CRegion& translate(const Vector2D& vec); CRegion& transform(const wl_output_transform t, double w, double h); CRegion& invert(pixman_box32_t* box); + CRegion& invert(const CBox& box); CRegion& scale(float scale); CBox getExtents(); bool containsPoint(const Vector2D& vec) const; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 770ca16a..e058f1c7 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2187,7 +2187,12 @@ bool CHyprRenderer::canSkipBackBufferClear(CMonitor* pMonitor) { ls->geometry.height != pMonitor->vecSize.y) continue; - if (!ls->layerSurface->surface->opaque) + // TODO: cache maybe? + CRegion opaque = &ls->layerSurface->surface->opaque_region; + CBox lsbox = {0, 0, ls->layerSurface->surface->current.buffer_width, ls->layerSurface->surface->current.buffer_height}; + opaque.invert(lsbox); + + if (!opaque.empty()) continue; return true; From adeb20ea114ff56d78804697e9ba8328f684b7b1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 26 Nov 2023 16:42:04 +0000 Subject: [PATCH 298/513] opengl: tiled special require introspection --- src/render/OpenGL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index f2cec5df..abb4a7d2 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -160,7 +160,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { return false; for (auto& w : g_pCompositor->m_vWindows) { - if (!w->m_bIsMapped || w->isHidden() || (!w->m_bIsFloating && *POPTIM)) + if (!w->m_bIsMapped || w->isHidden() || (!w->m_bIsFloating && *POPTIM && !g_pCompositor->isWorkspaceSpecial(w->m_iWorkspaceID))) continue; if (!g_pHyprRenderer->shouldRenderWindow(w.get())) From 1778fb77e20a7ff0c9fc20bb139b2e63fa41c7ef Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 26 Nov 2023 17:53:51 +0000 Subject: [PATCH 299/513] functionhooks: throw an exception on unsupported %rip usage ref #2479, now will actually tell you what's wrong instead of crashing --- src/plugins/HookSystem.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/plugins/HookSystem.cpp b/src/plugins/HookSystem.cpp index e6bd354b..97469e02 100644 --- a/src/plugins/HookSystem.cpp +++ b/src/plugins/HookSystem.cpp @@ -45,6 +45,10 @@ size_t CFunctionHook::getInstructionLenAt(void* start) { // I don't have an assembler. I don't think udis provides one. Besides, variables might be tricky. if (((uint8_t*)start)[0] == 0xFF && ((uint8_t*)start)[1] == 0x15) m_vTrampolineRIPUses.emplace_back(std::make_pair<>((uint64_t)start - (uint64_t)m_pSource, ins)); + else { + Debug::log(ERR, "[CFunctionHook] Cannot hook: unsupported %rip usage: {}", ins); + throw std::runtime_error("unsupported %rip usage"); + } } return insSize; @@ -90,7 +94,10 @@ bool CFunctionHook::hook() { static constexpr size_t CALL_WITH_RAX_ADDRESS_OFFSET = 2; // get minimum size to overwrite - const auto HOOKSIZE = probeMinimumJumpSize(m_pSource, sizeof(ABSOLUTE_JMP_ADDRESS) + sizeof(PUSH_RAX) + sizeof(POP_RAX)); + size_t HOOKSIZE = 0; + try { + HOOKSIZE = probeMinimumJumpSize(m_pSource, sizeof(ABSOLUTE_JMP_ADDRESS) + sizeof(PUSH_RAX) + sizeof(POP_RAX)); + } catch (std::exception& e) { return false; } // alloc trampoline const auto TRAMPOLINE_SIZE = sizeof(ABSOLUTE_JMP_ADDRESS) + HOOKSIZE + sizeof(PUSH_RAX) + m_vTrampolineRIPUses.size() * (sizeof(CALL_WITH_RAX) - 6); From 7a0a5666d565a3ef892a7ab433a5007dd1cc72dd Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Sun, 26 Nov 2023 17:59:49 +0000 Subject: [PATCH 300/513] groupbar: allow reload and fix locked groupbar gradient (#3546) modified: src/config/ConfigManager.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp modified: src/render/decorations/CHyprGroupBarDecoration.hpp --- src/config/ConfigManager.cpp | 7 ++++- .../decorations/CHyprGroupBarDecoration.cpp | 31 ++++++++++++------- .../decorations/CHyprGroupBarDecoration.hpp | 4 +-- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 54ecadb5..d02c5942 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1,6 +1,8 @@ #include "ConfigManager.hpp" #include "../managers/KeybindManager.hpp" +#include "../render/decorations/CHyprGroupBarDecoration.hpp" + #include #include #include @@ -79,7 +81,7 @@ void CConfigManager::setDefaultVars() { configValues["general:no_border_on_floating"].intValue = 0; configValues["general:gaps_in"].intValue = 5; configValues["general:gaps_out"].intValue = 20; - configValues["general:gaps_workspaces"].intValue = 0; + configValues["general:gaps_workspaces"].intValue = 0; ((CGradientValueData*)configValues["general:col.active_border"].data.get())->reset(0xffffffff); ((CGradientValueData*)configValues["general:col.inactive_border"].data.get())->reset(0xff444444); ((CGradientValueData*)configValues["general:col.nogroup_border"].data.get())->reset(0xff444444); @@ -1669,6 +1671,9 @@ void CConfigManager::loadConfigLoadVars() { ensureVRR(); } + if (!isFirstLaunch && !g_pCompositor->m_bUnsafeState) + refreshGroupBarGradients(); + // Updates dynamic window and workspace rules for (auto& w : g_pCompositor->m_vWindows) { if (!w->m_bIsMapped) diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 7d2c84ee..d36093ae 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -6,6 +6,9 @@ // shared things to conserve VRAM static CTexture m_tGradientActive; static CTexture m_tGradientInactive; +static CTexture m_tGradientLockedActive; +static CTexture m_tGradientLockedInactive; + constexpr int BAR_INDICATOR_HEIGHT = 3; constexpr int BAR_PADDING_OUTER_VERT = 2; constexpr int BAR_TEXT_PAD = 2; @@ -13,6 +16,8 @@ constexpr int BAR_HORIZONTAL_PADDING = 2; CHyprGroupBarDecoration::CHyprGroupBarDecoration(CWindow* pWindow) : IHyprWindowDecoration(pWindow) { m_pWindow = pWindow; + if (m_tGradientActive.m_iTexID == 0) + refreshGroupBarGradients(); } CHyprGroupBarDecoration::~CHyprGroupBarDecoration() {} @@ -130,10 +135,10 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale})) .get(); - refreshGradients(); - if (*PGRADIENTS) - g_pHyprOpenGL->renderTexture((m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? m_tGradientActive : m_tGradientInactive), &rect, 1.0); + g_pHyprOpenGL->renderTexture((m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) : + (GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive)), + &rect, 1.0); rect.y += (ASSIGNEDBOX.h / 2.0 - (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) / 2.0) * pMonitor->scale; rect.height = (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale; @@ -273,21 +278,23 @@ void renderGradientTo(CTexture& tex, const CColor& grad) { cairo_surface_destroy(CAIROSURFACE); } -void CHyprGroupBarDecoration::refreshGradients() { - if (m_tGradientActive.m_iTexID > 0) - return; - +void refreshGroupBarGradients() { static auto* const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.active")->data; static auto* const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.inactive")->data; static auto* const PGROUPCOLACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_active")->data; static auto* const PGROUPCOLINACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_inactive")->data; - const bool GROUPLOCKED = m_pWindow->getGroupHead()->m_sGroupData.locked; - const auto* const PCOLACTIVE = GROUPLOCKED ? PGROUPCOLACTIVELOCKED : PGROUPCOLACTIVE; - const auto* const PCOLINACTIVE = GROUPLOCKED ? PGROUPCOLINACTIVELOCKED : PGROUPCOLINACTIVE; + if (m_tGradientActive.m_iTexID != 0) { + m_tGradientActive.destroyTexture(); + m_tGradientInactive.destroyTexture(); + m_tGradientLockedActive.destroyTexture(); + m_tGradientLockedInactive.destroyTexture(); + } - renderGradientTo(m_tGradientActive, ((CGradientValueData*)PCOLACTIVE->get())->m_vColors[0]); - renderGradientTo(m_tGradientInactive, ((CGradientValueData*)PCOLINACTIVE->get())->m_vColors[0]); + renderGradientTo(m_tGradientActive, ((CGradientValueData*)PGROUPCOLACTIVE->get())->m_vColors[0]); + renderGradientTo(m_tGradientInactive, ((CGradientValueData*)PGROUPCOLINACTIVE->get())->m_vColors[0]); + renderGradientTo(m_tGradientLockedActive, ((CGradientValueData*)PGROUPCOLACTIVELOCKED->get())->m_vColors[0]); + renderGradientTo(m_tGradientLockedInactive, ((CGradientValueData*)PGROUPCOLINACTIVELOCKED->get())->m_vColors[0]); } bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D& pos) { diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp index 52439942..78edbeae 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.hpp +++ b/src/render/decorations/CHyprGroupBarDecoration.hpp @@ -16,6 +16,8 @@ class CTitleTex { CWindow* pWindowOwner = nullptr; }; +void refreshGroupBarGradients(); + class CHyprGroupBarDecoration : public IHyprWindowDecoration { public: CHyprGroupBarDecoration(CWindow*); @@ -57,8 +59,6 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { CTitleTex* textureFromTitle(const std::string&); void invalidateTextures(); - void refreshGradients(); - CBox assignedBoxGlobal(); struct STitleTexs { From e416ab740d224bddb865191a028ea1016d7be31e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 26 Nov 2023 18:02:23 +0000 Subject: [PATCH 301/513] config: log info about logs before loading vars --- src/config/ConfigManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index d02c5942..cf5f5972 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -33,6 +33,8 @@ CConfigManager::CConfigManager() { configValues["group:groupbar:col.locked_active"].data = std::make_shared(0x66ff5500); configValues["group:groupbar:col.locked_inactive"].data = std::make_shared(0x66775500); + Debug::log(LOG, "NOTE: further logs to stdout / logfile are disabled by default. Use debug:disable_logs and debug:enable_stdout_logs to override this."); + setDefaultVars(); setDefaultAnimationVars(); From 99ca26d4eb84e0071264713902e5b287fcab392e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 26 Nov 2023 18:33:53 +0000 Subject: [PATCH 302/513] hooksystem: fix missed log include --- src/plugins/HookSystem.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/HookSystem.cpp b/src/plugins/HookSystem.cpp index 97469e02..d7a366f3 100644 --- a/src/plugins/HookSystem.cpp +++ b/src/plugins/HookSystem.cpp @@ -1,4 +1,5 @@ #include "HookSystem.hpp" +#include "../debug/Log.hpp" #define register #include From e2f18f8c7f95e4094acb94c5a06dc6d75d7fc9c1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 28 Nov 2023 19:03:02 +0000 Subject: [PATCH 303/513] groupbar: more safety around gradient textures --- src/render/decorations/CHyprGroupBarDecoration.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index d36093ae..f315f56a 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -135,10 +135,11 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale})) .get(); - if (*PGRADIENTS) - g_pHyprOpenGL->renderTexture((m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) : - (GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive)), - &rect, 1.0); + const auto& GRADIENTTEX = (m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) : + (GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive)); + + if (*PGRADIENTS && GRADIENTTEX.m_iTexID != 0) + g_pHyprOpenGL->renderTexture(GRADIENTTEX, &rect, 1.0); rect.y += (ASSIGNEDBOX.h / 2.0 - (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) / 2.0) * pMonitor->scale; rect.height = (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale; From 3caaa483d4bf8f18f62f8a8f03a0922ea8a4cb7e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 29 Nov 2023 03:39:45 +0000 Subject: [PATCH 304/513] configmgr: fix parsing of touchdevice groups fixes #3992 --- src/config/ConfigManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index cf5f5972..07c1f51f 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1515,7 +1515,7 @@ void CConfigManager::parseLine(std::string& line) { const auto LASTSEP = currentCategory.find_last_of(':'); - if (LASTSEP == std::string::npos || currentCategory.contains("device")) + if (LASTSEP == std::string::npos || currentCategory.starts_with("device")) currentCategory = ""; else currentCategory = currentCategory.substr(0, LASTSEP); From b80c72c7ddbf79147d64759c8659eb5939d0327e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 29 Nov 2023 13:36:37 +0000 Subject: [PATCH 305/513] groupbar: fix crash in renderGradientTo fixes #3985 --- src/render/decorations/CHyprGroupBarDecoration.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index f315f56a..ae1d76a7 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -238,6 +238,9 @@ CTitleTex::~CTitleTex() { void renderGradientTo(CTexture& tex, const CColor& grad) { + if (!g_pCompositor->m_pLastMonitor) + return; + const Vector2D& bufferSize = g_pCompositor->m_pLastMonitor->vecPixelSize; const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, bufferSize.x, bufferSize.y); From d2c3b23ace745d3f79926c71d4cb3c481a394841 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 30 Nov 2023 01:18:55 +0000 Subject: [PATCH 306/513] deps: update wlroots --- src/Compositor.cpp | 4 +- src/events/Windows.cpp | 8 +-- src/protocols/Screencopy.cpp | 31 ++++----- src/render/OpenGL.cpp | 118 ++++++++++++----------------------- src/render/OpenGL.hpp | 7 ++- src/render/Renderer.cpp | 25 +++++--- src/render/Renderer.hpp | 22 ++++--- subprojects/wlroots | 2 +- 8 files changed, 96 insertions(+), 121 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index b0e1fcb3..5adfea86 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -190,7 +190,7 @@ void CCompositor::initServer() { m_sWLRGammaCtrlMgr = wlr_gamma_control_manager_v1_create(m_sWLDisplay); - m_sWLROutputLayout = wlr_output_layout_create(); + m_sWLROutputLayout = wlr_output_layout_create(m_sWLDisplay); m_sWLROutputPowerMgr = wlr_output_power_manager_v1_create(m_sWLDisplay); @@ -282,7 +282,7 @@ void CCompositor::initServer() { void CCompositor::initAllSignals() { addWLSignal(&m_sWLRBackend->events.new_output, &Events::listen_newOutput, m_sWLRBackend, "Backend"); - addWLSignal(&m_sWLRXDGShell->events.new_surface, &Events::listen_newXDGToplevel, m_sWLRXDGShell, "XDG Shell"); + addWLSignal(&m_sWLRXDGShell->events.new_toplevel, &Events::listen_newXDGToplevel, m_sWLRXDGShell, "XDG Shell"); addWLSignal(&m_sWLRCursor->events.motion, &Events::listen_mouseMove, m_sWLRCursor, "WLRCursor"); addWLSignal(&m_sWLRCursor->events.motion_absolute, &Events::listen_mouseMoveAbsolute, m_sWLRCursor, "WLRCursor"); addWLSignal(&m_sWLRCursor->events.button, &Events::listen_mouseButton, m_sWLRCursor, "WLRCursor"); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 556ec1b5..2ee70264 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -1171,12 +1171,10 @@ void Events::listener_surfaceXWayland(wl_listener* listener, void* data) { void Events::listener_newXDGToplevel(wl_listener* listener, void* data) { // A window got opened - const auto XDGSURFACE = (wlr_xdg_surface*)data; + const auto XDGTOPLEVEL = (wlr_xdg_toplevel*)data; + const auto XDGSURFACE = XDGTOPLEVEL->base; - if (XDGSURFACE->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) - return; - - Debug::log(LOG, "New XDG Surface created. (class: {})", XDGSURFACE->toplevel->app_id ? XDGSURFACE->toplevel->app_id : "null"); + Debug::log(LOG, "New XDG Toplevel created. (class: {})", XDGSURFACE->toplevel->app_id ? XDGSURFACE->toplevel->app_id : "null"); const auto PNEWWINDOW = g_pCompositor->m_vWindows.emplace_back(std::make_unique()).get(); PNEWWINDOW->m_uSurface.xdg = XDGSURFACE; diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index f0f0f69e..fdd89d30 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -424,23 +424,26 @@ void CScreencopyProtocolManager::sendFrameDamage(SScreencopyFrame* frame) { } bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* now) { - void* data; - uint32_t format; - size_t stride; - if (!wlr_buffer_begin_data_ptr_access(frame->buffer, WLR_BUFFER_DATA_PTR_ACCESS_WRITE, &data, &format, &stride)) - return false; + // void* data; + // uint32_t format; + // size_t stride; + // if (!wlr_buffer_begin_data_ptr_access(frame->buffer, WLR_BUFFER_DATA_PTR_ACCESS_WRITE, &data, &format, &stride)) + // return false; - if (!wlr_renderer_begin_with_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer)) { - Debug::log(ERR, "[sc] shm: Client requested a copy to a buffer that failed to pass wlr_renderer_begin_with_buffer"); - wlr_buffer_end_data_ptr_access(frame->buffer); - return false; - } + // if (!wlr_renderer_begin_with_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer)) { + // Debug::log(ERR, "[sc] shm: Client requested a copy to a buffer that failed to pass wlr_renderer_begin_with_buffer"); + // wlr_buffer_end_data_ptr_access(frame->buffer); + // return false; + // } - bool success = wlr_renderer_read_pixels(g_pCompositor->m_sWLRRenderer, format, stride, frame->box.width, frame->box.height, frame->box.x, frame->box.y, 0, 0, data); - wlr_renderer_end(g_pCompositor->m_sWLRRenderer); - wlr_buffer_end_data_ptr_access(frame->buffer); + // bool success = wlr_renderer_read_pixels(g_pCompositor->m_sWLRRenderer, format, stride, frame->box.width, frame->box.height, frame->box.x, frame->box.y, 0, 0, data); + // wlr_renderer_end(g_pCompositor->m_sWLRRenderer); + // wlr_buffer_end_data_ptr_access(frame->buffer); - return success; + // return success; + + return false; // TODO: maybe fix this with the new rendering pipeline? + // though who tf isnt using dmabuf? } bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) { diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index abb4a7d2..59836524 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -123,6 +123,12 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { static auto* const POPTIM = &g_pConfigManager->getConfigValuePtr("decoration:blur:new_optimizations")->intValue; static auto* const PBLURSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:blur:special")->intValue; + if (m_RenderData.mouseZoomFactor != 1.0) + return true; + + if (!pMonitor->mirrors.empty()) + return true; + if (*PBLUR == 0) return false; @@ -178,7 +184,7 @@ bool CHyprOpenGLImpl::passRequiresIntrospection(CMonitor* pMonitor) { return false; } -void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { +void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, CFramebuffer* fb) { m_RenderData.pMonitor = pMonitor; TRACY_GPU_ZONE("RenderBegin"); @@ -214,35 +220,36 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, bool fake) { m_RenderData.damage.set(*pDamage); - m_bFakeFrame = fake; + m_bFakeFrame = fb; if (m_bReloadScreenShader) { m_bReloadScreenShader = false; applyScreenShader(g_pConfigManager->getString("decoration:screen_shader")); } - const auto PRBO = g_pHyprRenderer->getCurrentRBO(); + const auto PRBO = g_pHyprRenderer->getCurrentRBO(); + const bool FBPROPERSIZE = fb && fb->m_vSize == pMonitor->vecPixelSize; - if (m_sFinalScreenShader.program > 0 || m_bFakeFrame || m_RenderData.mouseZoomFactor != 1.0 || pMonitor->vecPixelSize != PRBO->getFB()->m_vSize || !pMonitor->mirrors.empty() || - passRequiresIntrospection(pMonitor)) { + if (!FBPROPERSIZE || m_sFinalScreenShader.program > 0 || (PRBO && pMonitor->vecPixelSize != PRBO->getFB()->m_vSize) || passRequiresIntrospection(pMonitor)) { // we have to offload - // bind the primary Hypr Framebuffer + // bind the offload Hypr Framebuffer m_RenderData.pCurrentMonData->offloadFB.bind(); m_RenderData.currentFB = &m_RenderData.pCurrentMonData->offloadFB; m_bOffloadedFramebuffer = true; } else { - // we can render to the rbo directly - const auto PFBO = PRBO->getFB(); + // we can render to the rbo / fbo (fake) directly + const auto PFBO = fb ? fb : PRBO->getFB(); m_RenderData.currentFB = PFBO; if (PFBO->m_pStencilTex != &m_RenderData.pCurrentMonData->stencilTex) { PFBO->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; PFBO->addStencil(); } - PRBO->bindFB(); + PFBO->bind(); m_bOffloadedFramebuffer = false; } m_RenderData.mainFB = m_RenderData.currentFB; + m_RenderData.outFB = fb ? fb : PRBO->getFB(); } void CHyprOpenGLImpl::end() { @@ -254,10 +261,10 @@ void CHyprOpenGLImpl::end() { saveBufferForMirror(); // save with original damage region // end the render, copy the data to the WLR framebuffer - if (m_bOffloadedFramebuffer && !m_bFakeFrame) { + if (m_bOffloadedFramebuffer) { m_RenderData.damage = m_RenderData.pMonitor->lastFrameDamage; - g_pHyprRenderer->getCurrentRBO()->bindFB(); + m_RenderData.outFB->bind(); CBox monbox = {0, 0, m_RenderData.pMonitor->vecTransformedSize.x, m_RenderData.pMonitor->vecTransformedSize.y}; @@ -1559,14 +1566,18 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(CWindow* pWindow, CFramebuffer* pFra if (!PMONITOR || !PMONITOR->output || PMONITOR->vecPixelSize.x <= 0 || PMONITOR->vecPixelSize.y <= 0) return; - wlr_output_attach_render(PMONITOR->output, nullptr); - // we need to "damage" the entire monitor // so that we render the entire window // this is temporary, doesnt mess with the actual wlr damage CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y}; - begin(PMONITOR, &fakeDamage, true); + g_pHyprRenderer->makeEGLCurrent(); + + pFramebuffer->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; + + pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat); + + g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, pFramebuffer); clear(CColor(0, 0, 0, 0)); // JIC @@ -1584,12 +1595,6 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(CWindow* pWindow, CFramebuffer* pFra // TODO: how can we make this the size of the window? setting it to window's size makes the entire screen render with the wrong res forever more. odd. glViewport(0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); - pFramebuffer->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; - - pFramebuffer->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat); - - pFramebuffer->bind(); - m_RenderData.currentFB = pFramebuffer; clear(CColor(0, 0, 0, 0)); // JIC @@ -1598,15 +1603,7 @@ void CHyprOpenGLImpl::makeRawWindowSnapshot(CWindow* pWindow, CFramebuffer* pFra g_pConfigManager->setInt("decoration:blur:enabled", BLURVAL); -// restore original fb -#ifndef GLES2 - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_iCurrentOutputFb); -#else - glBindFramebuffer(GL_FRAMEBUFFER, m_iCurrentOutputFb); -#endif - end(); - - wlr_output_rollback(PMONITOR->output); + g_pHyprRenderer->endRender(); } void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) { @@ -1619,14 +1616,18 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) { if (!g_pHyprRenderer->shouldRenderWindow(pWindow)) return; // ignore, window is not being rendered - wlr_output_attach_render(PMONITOR->output, nullptr); - // we need to "damage" the entire monitor // so that we render the entire window // this is temporary, doesnt mess with the actual wlr damage CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y}; - begin(PMONITOR, &fakeDamage, true); + g_pHyprRenderer->makeEGLCurrent(); + + const auto PFRAMEBUFFER = &m_mWindowFramebuffers[pWindow]; + + PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat); + + g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, PFRAMEBUFFER); g_pHyprRenderer->m_bRenderingSnapshot = true; @@ -1643,35 +1644,15 @@ void CHyprOpenGLImpl::makeWindowSnapshot(CWindow* pWindow) { const auto BLURVAL = g_pConfigManager->getInt("decoration:blur:enabled"); g_pConfigManager->setInt("decoration:blur:enabled", 0); - glViewport(0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y); - - const auto PFRAMEBUFFER = &m_mWindowFramebuffers[pWindow]; - - PFRAMEBUFFER->m_pStencilTex = &m_RenderData.pCurrentMonData->stencilTex; - - PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat); - - PFRAMEBUFFER->bind(); - - m_RenderData.currentFB = PFRAMEBUFFER; - clear(CColor(0, 0, 0, 0)); // JIC g_pHyprRenderer->renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders, RENDER_PASS_ALL); g_pConfigManager->setInt("decoration:blur:enabled", BLURVAL); -// restore original fb -#ifndef GLES2 - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_iCurrentOutputFb); -#else - glBindFramebuffer(GL_FRAMEBUFFER, m_iCurrentOutputFb); -#endif - end(); + g_pHyprRenderer->endRender(); g_pHyprRenderer->m_bRenderingSnapshot = false; - - wlr_output_rollback(PMONITOR->output); } void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) { @@ -1681,26 +1662,18 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) { if (!PMONITOR || !PMONITOR->output || PMONITOR->vecPixelSize.x <= 0 || PMONITOR->vecPixelSize.y <= 0) return; - wlr_output_attach_render(PMONITOR->output, nullptr); - // we need to "damage" the entire monitor // so that we render the entire window // this is temporary, doesnt mess with the actual wlr damage - CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y}; - - begin(PMONITOR, &fakeDamage, true); - - g_pHyprRenderer->m_bRenderingSnapshot = true; + CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y}; const auto PFRAMEBUFFER = &m_mLayerFramebuffers[pLayer]; - glViewport(0, 0, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.x, g_pHyprOpenGL->m_RenderData.pMonitor->vecPixelSize.y); - PFRAMEBUFFER->alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat); - PFRAMEBUFFER->bind(); + g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, PFRAMEBUFFER); - m_RenderData.currentFB = PFRAMEBUFFER; + g_pHyprRenderer->m_bRenderingSnapshot = true; clear(CColor(0, 0, 0, 0)); // JIC @@ -1715,20 +1688,9 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) { pLayer->forceBlur = BLURLSSTATUS; - // TODO: WARN: - // revise if any stencil-requiring rendering is done to the layers. - -// restore original fb -#ifndef GLES2 - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_iCurrentOutputFb); -#else - glBindFramebuffer(GL_FRAMEBUFFER, m_iCurrentOutputFb); -#endif - end(); + g_pHyprRenderer->endRender(); g_pHyprRenderer->m_bRenderingSnapshot = false; - - wlr_output_rollback(PMONITOR->output); } void CHyprOpenGLImpl::renderSnapshot(CWindow** pWindow) { @@ -2052,7 +2014,7 @@ void CHyprOpenGLImpl::clearWithTex() { } void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) { - wlr_output_attach_render(pMonitor->output, nullptr); + g_pHyprRenderer->makeEGLCurrent(); g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].mirrorFB.release(); g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].offloadFB.release(); @@ -2066,8 +2028,6 @@ void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) { g_pHyprOpenGL->m_mMonitorBGTextures.erase(pMonitor); Debug::log(LOG, "Monitor {} -> destroyed all render data", pMonitor->szName); - - wlr_output_rollback(pMonitor->output); } void CHyprOpenGLImpl::saveMatrix() { diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index ea2fe07e..f4661e1a 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -82,8 +82,9 @@ struct SCurrentRenderData { float savedProjection[9]; SMonitorRenderData* pCurrentMonData = nullptr; - CFramebuffer* currentFB = nullptr; - CFramebuffer* mainFB = nullptr; + CFramebuffer* currentFB = nullptr; // current rendering to + CFramebuffer* mainFB = nullptr; // main to render to + CFramebuffer* outFB = nullptr; // out to render to (if offloaded, etc) CRegion damage; @@ -107,7 +108,7 @@ class CHyprOpenGLImpl { public: CHyprOpenGLImpl(); - void begin(CMonitor*, CRegion*, bool fake = false); + void begin(CMonitor*, CRegion*, CFramebuffer* fb = nullptr /* if provided, it's not a real frame */); void end(); void renderRect(CBox*, const CColor&, int round = 0); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index e058f1c7..20bcdcd2 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2280,22 +2280,31 @@ CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(wlr_buffer* buffer, uint32 return m_vRenderbuffers.emplace_back(std::make_unique(buffer, fmt)).get(); } -bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, wlr_buffer* withBuffer) { - +void CHyprRenderer::makeEGLCurrent() { if (eglGetCurrentContext() != wlr_egl_get_context(g_pCompositor->m_sWLREGL)) eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)); +} + +void CHyprRenderer::unsetEGL() { + eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); +} + +bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode, wlr_buffer* buffer, CFramebuffer* fb) { + + makeEGLCurrent(); m_eRenderMode = mode; g_pHyprOpenGL->m_RenderData.pMonitor = pMonitor; // has to be set cuz allocs if (mode == RENDER_MODE_FULL_FAKE) { - wlr_output_attach_render(pMonitor->output, nullptr); - g_pHyprOpenGL->begin(pMonitor, &damage, true); + RASSERT(fb, "Cannot render FULL_FAKE without a provided fb!"); + fb->bind(); + g_pHyprOpenGL->begin(pMonitor, &damage, fb); return true; } - if (!withBuffer) { + if (!buffer) { if (!wlr_output_configure_primary_swapchain(pMonitor->output, &pMonitor->output->pending, &pMonitor->output->swapchain)) return false; @@ -2303,7 +2312,7 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode if (!m_pCurrentWlrBuffer) return false; } else { - m_pCurrentWlrBuffer = withBuffer; + m_pCurrentWlrBuffer = buffer; } try { @@ -2334,8 +2343,10 @@ void CHyprRenderer::endRender() { else glFlush(); - if (m_eRenderMode == RENDER_MODE_NORMAL) + if (m_eRenderMode == RENDER_MODE_NORMAL) { wlr_output_state_set_buffer(&PMONITOR->output->pending, m_pCurrentWlrBuffer); + unsetEGL(); // flush the context + } wlr_buffer_unlock(m_pCurrentWlrBuffer); diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 1107d993..3c21a84e 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -70,18 +70,20 @@ class CHyprRenderer { void onRenderbufferDestroy(CRenderbuffer* rb); CRenderbuffer* getCurrentRBO(); bool isNvidia(); + void makeEGLCurrent(); + void unsetEGL(); - bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, wlr_buffer* withBuffer = nullptr); - void endRender(); + bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, wlr_buffer* buffer = nullptr, CFramebuffer* fb = nullptr); + void endRender(); - bool m_bWindowRequestedCursorHide = false; - bool m_bBlockSurfaceFeedback = false; - bool m_bRenderingSnapshot = false; - CWindow* m_pLastScanout = nullptr; - CMonitor* m_pMostHzMonitor = nullptr; - bool m_bDirectScanoutBlocked = false; - bool m_bSoftwareCursorsLocked = false; - bool m_bTearingEnvSatisfied = false; + bool m_bWindowRequestedCursorHide = false; + bool m_bBlockSurfaceFeedback = false; + bool m_bRenderingSnapshot = false; + CWindow* m_pLastScanout = nullptr; + CMonitor* m_pMostHzMonitor = nullptr; + bool m_bDirectScanoutBlocked = false; + bool m_bSoftwareCursorsLocked = false; + bool m_bTearingEnvSatisfied = false; DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&); diff --git a/subprojects/wlroots b/subprojects/wlroots index 2eb22523..d7ecdad4 160000 --- a/subprojects/wlroots +++ b/subprojects/wlroots @@ -1 +1 @@ -Subproject commit 2eb225236eb72f27beec921e9f37ddf58e874fba +Subproject commit d7ecdad4e082cb5817806348de198679a11b35df From e1258707adeb3061600c43a5445063c5e3c59037 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 30 Nov 2023 01:19:51 +0000 Subject: [PATCH 307/513] [gha] Nix: update wlroots --- flake.lock | 8 ++++---- flake.nix | 2 +- subprojects/wlroots.wrap | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 4b31bc1a..052bd382 100644 --- a/flake.lock +++ b/flake.lock @@ -67,18 +67,18 @@ "flake": false, "locked": { "host": "gitlab.freedesktop.org", - "lastModified": 1700734054, - "narHash": "sha256-SBu1y01WjCSrcCKvgfCDDckrZjU/OmCJT8Xc+hPow7E=", + "lastModified": 1701291624, + "narHash": "sha256-SWmzxn3gTyZOGEHgSDUJjJdoEKtt/kV6uWrUDx4JCC4=", "owner": "wlroots", "repo": "wlroots", - "rev": "2eb225236eb72f27beec921e9f37ddf58e874fba", + "rev": "d7ecdad4e082cb5817806348de198679a11b35df", "type": "gitlab" }, "original": { "host": "gitlab.freedesktop.org", "owner": "wlroots", "repo": "wlroots", - "rev": "2eb225236eb72f27beec921e9f37ddf58e874fba", + "rev": "d7ecdad4e082cb5817806348de198679a11b35df", "type": "gitlab" } }, diff --git a/flake.nix b/flake.nix index 58f45c58..abe61306 100644 --- a/flake.nix +++ b/flake.nix @@ -12,7 +12,7 @@ host = "gitlab.freedesktop.org"; owner = "wlroots"; repo = "wlroots"; - rev = "2eb225236eb72f27beec921e9f37ddf58e874fba"; + rev = "d7ecdad4e082cb5817806348de198679a11b35df"; flake = false; }; diff --git a/subprojects/wlroots.wrap b/subprojects/wlroots.wrap index 7fb801b0..9b70bb97 100644 --- a/subprojects/wlroots.wrap +++ b/subprojects/wlroots.wrap @@ -1,7 +1,7 @@ [wrap-git] directory = wlroots url = https://gitlab.freedesktop.org/wlroots/wlroots.git -revision = 2eb225236eb72f27beec921e9f37ddf58e874fba +revision = d7ecdad4e082cb5817806348de198679a11b35df depth = 1 diff_files = wlroots-meson-build.patch From 1fc1e4e9cbc2569eb4d3841f22020f35e9642f12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Conzelmann?= <45296195+zephvr@users.noreply.github.com> Date: Thu, 30 Nov 2023 02:48:10 +0100 Subject: [PATCH 308/513] monitor: remove comma from monitor description (#3996) this allows for monitor specific rules to work on monitor with comma on their description fixes #2457 --- src/Compositor.cpp | 4 ++-- src/config/ConfigManager.cpp | 4 ++-- src/debug/HyprCtl.cpp | 4 ++-- src/helpers/Monitor.cpp | 6 +++++- src/helpers/Monitor.hpp | 1 + src/managers/KeybindManager.cpp | 2 +- 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 5adfea86..a842bb6b 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -574,7 +574,7 @@ CMonitor* CCompositor::getMonitorFromName(const std::string& name) { CMonitor* CCompositor::getMonitorFromDesc(const std::string& desc) { for (auto& m : m_vMonitors) { - if (m->output->description && std::string(m->output->description).starts_with(desc)) + if (m->szDescription.starts_with(desc)) return m.get(); } return nullptr; @@ -2059,7 +2059,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) { if (!m->output) continue; - if (m->output->description && std::string(m->output->description).starts_with(DESCRIPTION)) { + if (m->szDescription.starts_with(DESCRIPTION)) { return m.get(); } } diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 07c1f51f..257446ee 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2082,7 +2082,7 @@ void CConfigManager::performMonitorReload() { if (!m->output || m->isUnsafeFallback) continue; - auto rule = getMonitorRuleFor(m->szName, m->output->description ? m->output->description : ""); + auto rule = getMonitorRuleFor(m->szName, m->szDescription); if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule)) { overAgain = true; @@ -2163,7 +2163,7 @@ void CConfigManager::ensureMonitorStatus() { if (!rm->output || rm->isUnsafeFallback) continue; - auto rule = getMonitorRuleFor(rm->szName, rm->output->description ? rm->output->description : ""); + auto rule = getMonitorRuleFor(rm->szName, rm->szDescription); if (rule.disabled == rm->m_bEnabled) g_pHyprRenderer->applyMonitorRule(rm.get(), &rule); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 9745a0fe..91bbe264 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -75,7 +75,7 @@ std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat f "vrr": {}, "activelyTearing": {} }},)#", - m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->output->description ? m->output->description : ""), (m->output->make ? m->output->make : ""), + m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->szDescription), (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace, (m->activeWorkspace == -1 ? "" : escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName)), m->specialWorkspaceID, @@ -99,7 +99,7 @@ std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat f "{} {} {}\n\tscale: {:.2f}\n\ttransform: " "{}\n\tfocused: {}\n\tdpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\n", m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, - (m->output->description ? m->output->description : ""), (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), + m->szDescription, (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), m->activeWorkspace, (m->activeWorkspace == -1 ? "" : g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName), m->specialWorkspaceID, getWorkspaceNameFromSpecialID(m->specialWorkspaceID), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"), diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index f626bb3d..c1ae3503 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -50,6 +50,10 @@ void CMonitor::onConnect(bool noRule) { szName = output->name; + szDescription = output->description ? output->description : ""; + // remove comma character from description. This allow monitor specific rules to work on monitor with comma on their description + szDescription.erase(std::remove(szDescription.begin(), szDescription.end(), ','), szDescription.end()); + if (!wlr_backend_is_drm(output->backend)) createdByUser = true; // should be true. WL, X11 and Headless backends should be addable / removable @@ -651,4 +655,4 @@ void CMonitor::updateMatrix() { wlr_matrix_transform(projMatrix.data(), transform); wlr_matrix_translate(projMatrix.data(), -vecTransformedSize.x / 2.0, -vecTransformedSize.y / 2.0); } -} \ No newline at end of file +} diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index f354ca6d..7621ac17 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -43,6 +43,7 @@ class CMonitor { float scale = 1; std::string szName = ""; + std::string szDescription = ""; Vector2D vecReservedTopLeft = Vector2D(0, 0); Vector2D vecReservedBottomRight = Vector2D(0, 0); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 986de55e..11e2fa02 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1473,7 +1473,7 @@ void CKeybindManager::forceRendererReload(std::string args) { if (!m->output) continue; - auto rule = g_pConfigManager->getMonitorRuleFor(m->szName, m->output->description ? m->output->description : ""); + auto rule = g_pConfigManager->getMonitorRuleFor(m->szName, m->szDescription); if (!g_pHyprRenderer->applyMonitorRule(m.get(), &rule, true)) { overAgain = true; break; From 776f944619168e1812e7f8bee0258757fed987a4 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 30 Nov 2023 02:19:17 +0000 Subject: [PATCH 309/513] opengl: fix missed makeEGLCurrent fixes #3998 --- src/render/OpenGL.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 59836524..ee273dc4 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1665,7 +1665,9 @@ void CHyprOpenGLImpl::makeLayerSnapshot(SLayerSurface* pLayer) { // we need to "damage" the entire monitor // so that we render the entire window // this is temporary, doesnt mess with the actual wlr damage - CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y}; + CRegion fakeDamage{0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y}; + + g_pHyprRenderer->makeEGLCurrent(); const auto PFRAMEBUFFER = &m_mLayerFramebuffers[pLayer]; From b9937484f4deefbc07c5fc3483d15885068e975d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 30 Nov 2023 10:14:35 +0000 Subject: [PATCH 310/513] screencopy: fix broken shm copying fixes #4001 --- src/protocols/Screencopy.cpp | 60 +++++++++++++++++++++++--------- src/protocols/ToplevelExport.cpp | 7 +++- src/render/Renderer.cpp | 16 +++++---- src/render/Renderer.hpp | 7 ++-- 4 files changed, 64 insertions(+), 26 deletions(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index fdd89d30..2e00a509 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -424,26 +424,54 @@ void CScreencopyProtocolManager::sendFrameDamage(SScreencopyFrame* frame) { } bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* now) { - // void* data; - // uint32_t format; - // size_t stride; - // if (!wlr_buffer_begin_data_ptr_access(frame->buffer, WLR_BUFFER_DATA_PTR_ACCESS_WRITE, &data, &format, &stride)) - // return false; + wlr_texture* sourceTex = wlr_texture_from_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer); + if (!sourceTex) + return false; - // if (!wlr_renderer_begin_with_buffer(g_pCompositor->m_sWLRRenderer, m_pLastMonitorBackBuffer)) { - // Debug::log(ERR, "[sc] shm: Client requested a copy to a buffer that failed to pass wlr_renderer_begin_with_buffer"); - // wlr_buffer_end_data_ptr_access(frame->buffer); - // return false; - // } + void* data; + uint32_t format; + size_t stride; + if (!wlr_buffer_begin_data_ptr_access(frame->buffer, WLR_BUFFER_DATA_PTR_ACCESS_WRITE, &data, &format, &stride)) { + wlr_texture_destroy(sourceTex); + return false; + } - // bool success = wlr_renderer_read_pixels(g_pCompositor->m_sWLRRenderer, format, stride, frame->box.width, frame->box.height, frame->box.x, frame->box.y, 0, 0, data); - // wlr_renderer_end(g_pCompositor->m_sWLRRenderer); - // wlr_buffer_end_data_ptr_access(frame->buffer); + CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX}; - // return success; + g_pHyprRenderer->makeEGLCurrent(); - return false; // TODO: maybe fix this with the new rendering pipeline? - // though who tf isnt using dmabuf? + CFramebuffer fb; + fb.alloc(frame->box.w, frame->box.h); // 8bit only + + if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb)) { + wlr_texture_destroy(sourceTex); + wlr_buffer_end_data_ptr_access(frame->buffer); + return false; + } + + CBox monbox = CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y}.translate({-frame->box.x, -frame->box.y}); + g_pHyprOpenGL->setMonitorTransformEnabled(false); + g_pHyprOpenGL->renderTexture(sourceTex, &monbox, 1); + g_pHyprOpenGL->setMonitorTransformEnabled(true); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.m_iFb); + + const auto PFORMAT = gles2FromDRM(format); + if (!PFORMAT) { + Debug::log(ERR, "[sc] Cannot read pixels, unsupported format {:x}", (uintptr_t)PFORMAT); + wlr_texture_destroy(sourceTex); + wlr_buffer_end_data_ptr_access(frame->buffer); + return false; + } + + glReadPixels(0, 0, frame->box.w, frame->box.h, PFORMAT->gl_format, PFORMAT->gl_type, data); + + g_pHyprRenderer->endRender(); + + wlr_buffer_end_data_ptr_access(frame->buffer); + wlr_texture_destroy(sourceTex); + + return true; } bool CScreencopyProtocolManager::copyFrameDmabuf(SScreencopyFrame* frame) { diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 6c626e87..ef9906d9 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -363,7 +363,12 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times const auto PMONITOR = g_pCompositor->getMonitorFromID(frame->pWindow->m_iMonitorID); CRegion fakeDamage{0, 0, PMONITOR->vecPixelSize.x * 10, PMONITOR->vecPixelSize.y * 10}; - if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE)) { + g_pHyprRenderer->makeEGLCurrent(); + + CFramebuffer outFB; + outFB.alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); + + if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &outFB)) { wlr_buffer_end_data_ptr_access(frame->buffer); return false; } diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 20bcdcd2..b7b6ae96 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2312,7 +2312,7 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode if (!m_pCurrentWlrBuffer) return false; } else { - m_pCurrentWlrBuffer = buffer; + m_pCurrentWlrBuffer = wlr_buffer_lock(buffer); } try { @@ -2331,13 +2331,17 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode void CHyprRenderer::endRender() { const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor; - g_pHyprOpenGL->end(); - - if (m_eRenderMode == RENDER_MODE_FULL_FAKE) { - wlr_output_rollback(PMONITOR->output); - return; + if (m_eRenderMode != RENDER_MODE_TO_BUFFER_READ_ONLY) + g_pHyprOpenGL->end(); + else { + g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; + g_pHyprOpenGL->m_RenderData.mouseZoomFactor = 1.f; + g_pHyprOpenGL->m_RenderData.mouseZoomUseMouse = true; } + if (m_eRenderMode == RENDER_MODE_FULL_FAKE) + return; + if (isNvidia()) glFinish(); else diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 3c21a84e..aaafa257 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -30,9 +30,10 @@ enum eRenderPassMode enum eRenderMode { - RENDER_MODE_NORMAL = 0, - RENDER_MODE_FULL_FAKE = 1, - RENDER_MODE_TO_BUFFER = 2 + RENDER_MODE_NORMAL = 0, + RENDER_MODE_FULL_FAKE = 1, + RENDER_MODE_TO_BUFFER = 2, + RENDER_MODE_TO_BUFFER_READ_ONLY = 3, }; class CToplevelExportProtocolManager; From 9f2027be4bd888c5828412848bd73ba694ee2dbc Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 30 Nov 2023 10:15:02 +0000 Subject: [PATCH 311/513] opengl: don't make a mirror buffer on fakeFrame --- src/render/OpenGL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index ee273dc4..dbdabdad 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -257,7 +257,7 @@ void CHyprOpenGLImpl::end() { TRACY_GPU_ZONE("RenderEnd"); - if (!m_RenderData.pMonitor->mirrors.empty()) + if (!m_RenderData.pMonitor->mirrors.empty() && !m_bFakeFrame) saveBufferForMirror(); // save with original damage region // end the render, copy the data to the WLR framebuffer From 12ec549a183abd59779a294c2f5bca0e95e528c0 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 30 Nov 2023 11:07:17 +0000 Subject: [PATCH 312/513] screencopy: fix shm sharing if introspection required --- src/protocols/Screencopy.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 2e00a509..50528ca3 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -464,9 +464,15 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* return false; } + g_pHyprRenderer->endRender(); + + g_pHyprRenderer->makeEGLCurrent(); + g_pHyprOpenGL->m_RenderData.pMonitor = frame->pMonitor; + fb.bind(); + glReadPixels(0, 0, frame->box.w, frame->box.h, PFORMAT->gl_format, PFORMAT->gl_type, data); - g_pHyprRenderer->endRender(); + g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; wlr_buffer_end_data_ptr_access(frame->buffer); wlr_texture_destroy(sourceTex); From 29970228c5f71f417b0a3e1b4851d9430ed095dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= <123550+andresilva@users.noreply.github.com> Date: Thu, 30 Nov 2023 11:40:14 +0000 Subject: [PATCH 313/513] nix: override libdrm to use newer version (#4003) --- nix/default.nix | 13 ++++++++++++- nix/wlroots.nix | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/nix/default.nix b/nix/default.nix index 42808a5f..7ddeae94 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -1,5 +1,6 @@ { lib, + fetchurl, stdenv, pkg-config, makeWrapper, @@ -38,6 +39,16 @@ nvidiaPatches ? false, hidpiXWayland ? false, }: +let + # NOTE: remove after https://github.com/NixOS/nixpkgs/pull/271096 reaches nixos-unstable + libdrm_2_4_118 = libdrm.overrideAttrs(attrs: rec { + version = "2.4.118"; + src = fetchurl { + url = "https://dri.freedesktop.org/${attrs.pname}/${attrs.pname}-${version}.tar.xz"; + hash = "sha256-p3e9hfK1/JxX+IbIIFgwBXgxfK/bx30Kdp1+mpVnq4g="; + }; + }); +in assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed."; assert lib.assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed."; assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland"; @@ -74,7 +85,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov cairo hyprland-protocols libGL - libdrm + libdrm_2_4_118 libinput libxkbcommon mesa diff --git a/nix/wlroots.nix b/nix/wlroots.nix index f48ba35c..0b9186e9 100644 --- a/nix/wlroots.nix +++ b/nix/wlroots.nix @@ -1,18 +1,31 @@ { + fetchurl, version, src, wlroots, hwdata, libdisplay-info, libliftoff, + libdrm, enableXWayland ? true, }: +let + # NOTE: remove after https://github.com/NixOS/nixpkgs/pull/271096 reaches nixos-unstable + libdrm_2_4_118 = libdrm.overrideAttrs(old: rec { + version = "2.4.118"; + src = fetchurl { + url = "https://dri.freedesktop.org/${old.pname}/${old.pname}-${version}.tar.xz"; + hash = "sha256-p3e9hfK1/JxX+IbIIFgwBXgxfK/bx30Kdp1+mpVnq4g="; + }; + }); +in wlroots.overrideAttrs (old: { inherit version src enableXWayland; pname = "${old.pname}-hyprland"; - buildInputs = old.buildInputs ++ [hwdata libliftoff libdisplay-info]; + # HACK: libdrm_2_4_118 is placed at the head of list to take precedence over libdrm in `old.buildInputs` + buildInputs = [libdrm_2_4_118] ++ old.buildInputs ++ [hwdata libliftoff libdisplay-info]; NIX_CFLAGS_COMPILE = toString [ "-Wno-error=maybe-uninitialized" From 5513eed64d46ef542a2dfaeb4a3229e1d195b02b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Conzelmann?= <45296195+zephvr@users.noreply.github.com> Date: Thu, 30 Nov 2023 16:20:08 +0100 Subject: [PATCH 314/513] managers: fix debug log using printf format (#4007) Some debug messages where using printf format style to print variable content instead of std::format format. --- src/managers/KeybindManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 11e2fa02..c61ad82e 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1903,7 +1903,7 @@ void CKeybindManager::alterZOrder(std::string args) { else if (POSITION == "bottom") g_pCompositor->changeWindowZOrder(PWINDOW, 0); else { - Debug::log(ERR, "alterZOrder: bad position: %s", POSITION); + Debug::log(ERR, "alterZOrder: bad position: {}", POSITION); return; } @@ -2055,7 +2055,7 @@ void CKeybindManager::moveWindowOrGroup(std::string args) { static auto* const PIGNOREGROUPLOCK = &g_pConfigManager->getConfigValuePtr("binds:ignore_group_lock")->intValue; if (!isDirection(args)) { - Debug::log(ERR, "Cannot move into group in direction %c, unsupported direction. Supported: l,r,u/t,d/b", arg); + Debug::log(ERR, "Cannot move into group in direction {}, unsupported direction. Supported: l,r,u/t,d/b", arg); return; } From b2f36231312427d65362521836484fddb6ff91f8 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 30 Nov 2023 18:44:58 +0000 Subject: [PATCH 315/513] events: add keyPress and mouseAxis fixes #4011 fixes #4008 --- src/managers/input/InputManager.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index be5d296e..fe7bb75b 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -688,7 +688,10 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) { auto factor = (*PSCROLLFACTOR <= 0.f || e->source != WLR_AXIS_SOURCE_FINGER ? 1.f : *PSCROLLFACTOR); - bool passEvent = g_pKeybindManager->onAxisEvent(e); + const auto EMAP = std::unordered_map{{"event", e}}; + EMIT_HOOK_EVENT_CANCELLABLE("mouseAxis", EMAP); + + bool passEvent = g_pKeybindManager->onAxisEvent(e); g_pCompositor->notifyIdleActivity(); @@ -1152,6 +1155,9 @@ void CInputManager::onKeyboardKey(wlr_keyboard_key_event* e, SKeyboard* pKeyboar if (!pKeyboard->enabled) return; + const auto EMAP = std::unordered_map{{"keyboard", pKeyboard}, {"event", e}}; + EMIT_HOOK_EVENT_CANCELLABLE("keyPress", EMAP); + static auto* const PDPMS = &g_pConfigManager->getConfigValuePtr("misc:key_press_enables_dpms")->intValue; if (*PDPMS && !g_pCompositor->m_bDPMSStateON) { // enable dpms @@ -1645,7 +1651,7 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) { CBox box = w->getWindowMainSurfaceBox(); eBorderIconDirection direction = BORDERICON_NONE; CBox boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE), - box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; + box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; if (w->hasPopupAt(mouseCoords)) direction = BORDERICON_NONE; From 0a4c4da5f0dde3a24ef8c64aa65a9d21fe074370 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 30 Nov 2023 18:52:49 +0000 Subject: [PATCH 316/513] deps: update wlroots --- subprojects/wlroots | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subprojects/wlroots b/subprojects/wlroots index d7ecdad4..5d639394 160000 --- a/subprojects/wlroots +++ b/subprojects/wlroots @@ -1 +1 @@ -Subproject commit d7ecdad4e082cb5817806348de198679a11b35df +Subproject commit 5d639394f3e83b01596dcd166a44a9a1a2583350 From b394c1695c05cf3b2133a473aa459d4cd750911b Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 30 Nov 2023 18:53:34 +0000 Subject: [PATCH 317/513] [gha] Nix: update wlroots --- flake.lock | 8 ++++---- flake.nix | 2 +- subprojects/wlroots.wrap | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 052bd382..a7743fd0 100644 --- a/flake.lock +++ b/flake.lock @@ -67,18 +67,18 @@ "flake": false, "locked": { "host": "gitlab.freedesktop.org", - "lastModified": 1701291624, - "narHash": "sha256-SWmzxn3gTyZOGEHgSDUJjJdoEKtt/kV6uWrUDx4JCC4=", + "lastModified": 1701368958, + "narHash": "sha256-7kvyoA91etzVEl9mkA/EJfB6z/PltxX7Xc4gcr7/xlo=", "owner": "wlroots", "repo": "wlroots", - "rev": "d7ecdad4e082cb5817806348de198679a11b35df", + "rev": "5d639394f3e83b01596dcd166a44a9a1a2583350", "type": "gitlab" }, "original": { "host": "gitlab.freedesktop.org", "owner": "wlroots", "repo": "wlroots", - "rev": "d7ecdad4e082cb5817806348de198679a11b35df", + "rev": "5d639394f3e83b01596dcd166a44a9a1a2583350", "type": "gitlab" } }, diff --git a/flake.nix b/flake.nix index abe61306..a6d723f2 100644 --- a/flake.nix +++ b/flake.nix @@ -12,7 +12,7 @@ host = "gitlab.freedesktop.org"; owner = "wlroots"; repo = "wlroots"; - rev = "d7ecdad4e082cb5817806348de198679a11b35df"; + rev = "5d639394f3e83b01596dcd166a44a9a1a2583350"; flake = false; }; diff --git a/subprojects/wlroots.wrap b/subprojects/wlroots.wrap index 9b70bb97..3624d5aa 100644 --- a/subprojects/wlroots.wrap +++ b/subprojects/wlroots.wrap @@ -1,7 +1,7 @@ [wrap-git] directory = wlroots url = https://gitlab.freedesktop.org/wlroots/wlroots.git -revision = d7ecdad4e082cb5817806348de198679a11b35df +revision = 5d639394f3e83b01596dcd166a44a9a1a2583350 depth = 1 diff_files = wlroots-meson-build.patch From ab40f240c3211412641fdf05b52bf0f1b033fa7d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 1 Dec 2023 00:22:49 +0000 Subject: [PATCH 318/513] screencopy: use drmFormat instead of wlr funcs ref #4014 --- src/protocols/Screencopy.cpp | 2 +- src/protocols/ToplevelExport.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 50528ca3..7240fd37 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -210,7 +210,7 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r PFRAME->client = PCLIENT; PCLIENT->ref++; - PFRAME->shmFormat = g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XRGB8888 : wlr_output_preferred_read_format(PFRAME->pMonitor->output); + PFRAME->shmFormat = g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XRGB8888 : PFRAME->pMonitor->drmFormat; if (PFRAME->shmFormat == DRM_FORMAT_INVALID) { Debug::log(ERR, "No format supported by renderer in capture output"); zwlr_screencopy_frame_v1_send_failed(PFRAME->resource); diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index ef9906d9..aa035b6e 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -177,7 +177,7 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou const auto PMONITOR = g_pCompositor->getMonitorFromID(PFRAME->pWindow->m_iMonitorID); - PFRAME->shmFormat = g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XRGB8888 : wlr_output_preferred_read_format(PMONITOR->output); + PFRAME->shmFormat = g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XRGB8888 : PMONITOR->drmFormat; if (PFRAME->shmFormat == DRM_FORMAT_INVALID) { Debug::log(ERR, "No format supported by renderer in capture toplevel"); hyprland_toplevel_export_frame_v1_send_failed(resource); From 8440a30231ea41a6b1dacc60a28837b265a6efec Mon Sep 17 00:00:00 2001 From: Wren Baxter Date: Thu, 30 Nov 2023 20:12:08 -0500 Subject: [PATCH 319/513] input: fix overzealous mouse capture on resize_on_border (#4010) fixes #2456 --- src/managers/input/InputManager.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index fe7bb75b..77eabeb7 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -597,6 +597,9 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { const auto PASS = g_pKeybindManager->onMouseEvent(e); static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue; + static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; + static auto* const PBORDERGRABEXTEND = &g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area")->intValue; + const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0; if (!PASS && !*PPASSMOUSE) return; @@ -621,7 +624,8 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { if (*PRESIZEONBORDER && !m_bLastFocusOnLS) { if (w && !w->m_bIsFullscreen) { const CBox real = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; - if ((!real.containsPoint(mouseCoords) || w->isInCurvedCorner(mouseCoords.x, mouseCoords.y)) && !w->hasPopupAt(mouseCoords)) { + const CBox grab = {real.x - BORDER_GRAB_AREA, real.y - BORDER_GRAB_AREA, real.width + 2 * BORDER_GRAB_AREA, real.height + 2 * BORDER_GRAB_AREA}; + if ((grab.containsPoint(mouseCoords) && (!real.containsPoint(mouseCoords) || w->isInCurvedCorner(mouseCoords.x, mouseCoords.y))) && !w->hasPopupAt(mouseCoords)) { g_pKeybindManager->resizeWithBorder(e); return; } From 9c09f2a847a1372c73cf67dc9e7e9ebe309b142e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 1 Dec 2023 17:20:56 +0000 Subject: [PATCH 320/513] screencopy: fix shm exports with 10-bit fixes #4019 --- src/helpers/MiscFunctions.cpp | 10 ++++++++++ src/helpers/MiscFunctions.hpp | 1 + src/protocols/Screencopy.cpp | 15 +++++---------- src/protocols/ToplevelExport.cpp | 18 +++++------------- src/render/Framebuffer.cpp | 8 +------- src/render/OpenGL.cpp | 13 +++++++++++++ src/render/OpenGL.hpp | 2 ++ 7 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 71263748..16650e1b 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -781,4 +781,14 @@ uint32_t drmFormatToGL(uint32_t drm) { } UNREACHABLE(); return GL_RGBA; +} + +uint32_t glFormatToType(uint32_t gl) { + return gl != GL_RGBA ? +#ifdef GLES2 + GL_UNSIGNED_INT_2_10_10_10_REV_EXT : +#else + GL_UNSIGNED_INT_2_10_10_10_REV : +#endif + GL_UNSIGNED_BYTE; } \ No newline at end of file diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index 90479121..d8070c76 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -34,6 +34,7 @@ std::string replaceInString(std::string subject, const std: std::vector getBacktrace(); void throwError(const std::string& err); uint32_t drmFormatToGL(uint32_t drm); +uint32_t glFormatToType(uint32_t gl); template [[deprecated("use std::format instead")]] std::string getFormat(std::format_string fmt, Args&&... args) { diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 7240fd37..6c7178c0 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -210,7 +210,7 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r PFRAME->client = PCLIENT; PCLIENT->ref++; - PFRAME->shmFormat = g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XRGB8888 : PFRAME->pMonitor->drmFormat; + PFRAME->shmFormat = g_pHyprOpenGL->getPreferredReadFormat(PFRAME->pMonitor); if (PFRAME->shmFormat == DRM_FORMAT_INVALID) { Debug::log(ERR, "No format supported by renderer in capture output"); zwlr_screencopy_frame_v1_send_failed(PFRAME->resource); @@ -441,7 +441,7 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* g_pHyprRenderer->makeEGLCurrent(); CFramebuffer fb; - fb.alloc(frame->box.w, frame->box.h); // 8bit only + fb.alloc(frame->box.w, frame->box.h, frame->pMonitor->drmFormat); if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb)) { wlr_texture_destroy(sourceTex); @@ -456,13 +456,8 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.m_iFb); - const auto PFORMAT = gles2FromDRM(format); - if (!PFORMAT) { - Debug::log(ERR, "[sc] Cannot read pixels, unsupported format {:x}", (uintptr_t)PFORMAT); - wlr_texture_destroy(sourceTex); - wlr_buffer_end_data_ptr_access(frame->buffer); - return false; - } + const auto GLFORMAT = drmFormatToGL(frame->pMonitor->drmFormat); + const auto GLTYPE = glFormatToType(GLFORMAT); g_pHyprRenderer->endRender(); @@ -470,7 +465,7 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* g_pHyprOpenGL->m_RenderData.pMonitor = frame->pMonitor; fb.bind(); - glReadPixels(0, 0, frame->box.w, frame->box.h, PFORMAT->gl_format, PFORMAT->gl_type, data); + glReadPixels(0, 0, frame->box.w, frame->box.h, GL_RGBA, GLTYPE, data); g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index aa035b6e..d68aa616 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -177,7 +177,7 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou const auto PMONITOR = g_pCompositor->getMonitorFromID(PFRAME->pWindow->m_iMonitorID); - PFRAME->shmFormat = g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XRGB8888 : PMONITOR->drmFormat; + PFRAME->shmFormat = g_pHyprOpenGL->getPreferredReadFormat(PFRAME->pMonitor); if (PFRAME->shmFormat == DRM_FORMAT_INVALID) { Debug::log(ERR, "No format supported by renderer in capture toplevel"); hyprland_toplevel_export_frame_v1_send_failed(resource); @@ -366,7 +366,7 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times g_pHyprRenderer->makeEGLCurrent(); CFramebuffer outFB; - outFB.alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y); + outFB.alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat); if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &outFB)) { wlr_buffer_end_data_ptr_access(frame->buffer); @@ -386,20 +386,12 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times if (frame->overlayCursor) g_pHyprRenderer->renderSoftwareCursors(PMONITOR, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.vec()); - // copy pixels - const auto PFORMAT = gles2FromDRM(format); - if (!PFORMAT) { - Debug::log(ERR, "[toplevel_export] Cannot read pixels, unsupported format {:x}", (uintptr_t)PFORMAT); - g_pHyprRenderer->endRender(); - wlr_buffer_end_data_ptr_access(frame->buffer); - if (frame->overlayCursor) - wlr_output_lock_software_cursors(PMONITOR->output, false); - return false; - } + const auto GLFORMAT = drmFormatToGL(frame->pMonitor->drmFormat); + const auto GLTYPE = glFormatToType(GLFORMAT); g_pHyprOpenGL->m_RenderData.mainFB->bind(); - glReadPixels(0, 0, frame->box.width, frame->box.height, PFORMAT->gl_format, PFORMAT->gl_type, data); + glReadPixels(0, 0, frame->box.width, frame->box.height, GL_RGBA, GLTYPE, data); g_pHyprRenderer->endRender(); diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp index 94b3f64a..eed23699 100644 --- a/src/render/Framebuffer.cpp +++ b/src/render/Framebuffer.cpp @@ -6,13 +6,7 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { RASSERT((w > 1 && h > 1), "cannot alloc a FB with negative / zero size! (attempted {}x{})", w, h); uint32_t glFormat = drmFormatToGL(drmFormat); - uint32_t glType = glFormat != GL_RGBA ? -#ifdef GLES2 - GL_UNSIGNED_INT_2_10_10_10_REV_EXT : -#else - GL_UNSIGNED_INT_2_10_10_10_REV : -#endif - GL_UNSIGNED_BYTE; + uint32_t glType = glFormatToType(glFormat); if (m_iFb == (uint32_t)-1) { firstAlloc = true; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index dbdabdad..4eb45d8f 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2064,3 +2064,16 @@ void CHyprOpenGLImpl::bindBackOnMain() { void CHyprOpenGLImpl::setMonitorTransformEnabled(bool enabled) { m_bEndFrame = !enabled; } + +uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) { + if (g_pHyprRenderer->isNvidia()) + return DRM_FORMAT_XRGB8888; + + if (pMonitor->drmFormat == DRM_FORMAT_XRGB8888) + return DRM_FORMAT_XRGB8888; + if (pMonitor->drmFormat == DRM_FORMAT_XBGR8888) + return DRM_FORMAT_XBGR8888; + if (pMonitor->drmFormat == DRM_FORMAT_XRGB2101010 || pMonitor->drmFormat == DRM_FORMAT_XBGR2101010) + return DRM_FORMAT_XBGR2101010; + return DRM_FORMAT_INVALID; +} diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index f4661e1a..2830870b 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -158,6 +158,8 @@ class CHyprOpenGLImpl { void renderOffToMain(CFramebuffer* off); void bindBackOnMain(); + uint32_t getPreferredReadFormat(CMonitor* pMonitor); + SCurrentRenderData m_RenderData; GLint m_iCurrentOutputFb = 0; From 6e8b9ef7d8aa53247d5122b6641b9afa0df798df Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 1 Dec 2023 17:23:50 +0000 Subject: [PATCH 321/513] opengl: fix swapped rgb drm formats --- src/render/OpenGL.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 4eb45d8f..30187862 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2070,9 +2070,9 @@ uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) { return DRM_FORMAT_XRGB8888; if (pMonitor->drmFormat == DRM_FORMAT_XRGB8888) - return DRM_FORMAT_XRGB8888; - if (pMonitor->drmFormat == DRM_FORMAT_XBGR8888) return DRM_FORMAT_XBGR8888; + if (pMonitor->drmFormat == DRM_FORMAT_XBGR8888) + return DRM_FORMAT_XRGB8888; if (pMonitor->drmFormat == DRM_FORMAT_XRGB2101010 || pMonitor->drmFormat == DRM_FORMAT_XBGR2101010) return DRM_FORMAT_XBGR2101010; return DRM_FORMAT_INVALID; From 758cf90ea1066eea361a9d8c347e7fcf40f6636f Mon Sep 17 00:00:00 2001 From: thejch <66577496+thejch@users.noreply.github.com> Date: Sat, 2 Dec 2023 06:42:49 -0800 Subject: [PATCH 322/513] workspacerules: Add workspace rule for master layout orientation (#3964) * add workspace rule for master layout orientation * change rule format * edit rule name * use map for layoutopts * use std::any instead of string --- src/config/ConfigManager.cpp | 2 ++ src/config/ConfigManager.hpp | 29 +++++++++++++++-------------- src/layout/MasterLayout.cpp | 16 ++++++++++++---- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 257446ee..5659667e 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1214,6 +1214,8 @@ void CConfigManager::handleWorkspaceRules(const std::string& command, const std: wsRule.isPersistent = configStringToInt(rule.substr(delim + 11)); else if ((delim = rule.find(ruleOnCreatedEmtpy)) != std::string::npos) wsRule.onCreatedEmptyRunCmd = cleanCmdForWorkspace(name, rule.substr(delim + ruleOnCreatedEmtpyLen)); + else if ((delim = rule.find("layoutopt:orientation:")) != std::string::npos) + wsRule.layoutopts["orientation"] = rule.substr(delim + 22); }; size_t pos = 0; diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index f89ae72c..8009100e 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -37,20 +37,21 @@ struct SConfigValue { }; struct SWorkspaceRule { - std::string monitor = ""; - std::string workspaceString = ""; - std::string workspaceName = ""; - int workspaceId = -1; - bool isDefault = false; - bool isPersistent = false; - std::optional gapsIn; - std::optional gapsOut; - std::optional borderSize; - std::optional border; - std::optional rounding; - std::optional decorate; - std::optional shadow; - std::optional onCreatedEmptyRunCmd; + std::string monitor = ""; + std::string workspaceString = ""; + std::string workspaceName = ""; + int workspaceId = -1; + bool isDefault = false; + bool isPersistent = false; + std::optional gapsIn; + std::optional gapsOut; + std::optional borderSize; + std::optional border; + std::optional rounding; + std::optional decorate; + std::optional shadow; + std::optional onCreatedEmptyRunCmd; + std::map layoutopts; }; struct SMonitorAdditionalReservedArea { diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index d355a7d3..3977d8f6 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -42,13 +42,21 @@ SMasterWorkspaceData* CHyprMasterLayout::getMasterWorkspaceData(const int& ws) { const auto PWORKSPACEDATA = &m_lMasterWorkspacesData.emplace_back(); PWORKSPACEDATA->workspaceID = ws; const auto orientation = &g_pConfigManager->getConfigValuePtr("master:orientation")->strValue; - if (*orientation == "top") { + const auto layoutoptsForWs = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(ws)).layoutopts; + auto orientationForWs = *orientation; + + try { + if (layoutoptsForWs.contains("orientation")) + orientationForWs = std::any_cast(layoutoptsForWs.at("orientation")); + } catch (std::exception& e) { Debug::log(ERR, "Error from layoutopt rules: {}", e.what()); } + + if (orientationForWs == "top") { PWORKSPACEDATA->orientation = ORIENTATION_TOP; - } else if (*orientation == "right") { + } else if (orientationForWs == "right") { PWORKSPACEDATA->orientation = ORIENTATION_RIGHT; - } else if (*orientation == "bottom") { + } else if (orientationForWs == "bottom") { PWORKSPACEDATA->orientation = ORIENTATION_BOTTOM; - } else if (*orientation == "left") { + } else if (orientationForWs == "left") { PWORKSPACEDATA->orientation = ORIENTATION_LEFT; } else { PWORKSPACEDATA->orientation = ORIENTATION_CENTER; From 80b9b21f9f24b6e8db2fc6f7705cd124f436ffba Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 2 Dec 2023 14:51:35 +0000 Subject: [PATCH 323/513] opengl: fix nvidia read formats fixes #4023 --- src/render/OpenGL.cpp | 10 +++++----- src/render/OpenGL.hpp | 4 ++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 30187862..cbfe56e8 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -35,6 +35,8 @@ CHyprOpenGLImpl::CHyprOpenGLImpl() { loadGLProc(&m_sProc.glEGLImageTargetRenderbufferStorageOES, "glEGLImageTargetRenderbufferStorageOES"); loadGLProc(&m_sProc.eglDestroyImageKHR, "eglDestroyImageKHR"); + m_sExts.EXT_read_format_bgra = m_szExtensions.contains("GL_EXT_read_format_bgra"); + #ifdef USE_TRACY_GPU loadGLProc(&glQueryCounter, "glQueryCounterEXT"); @@ -2067,12 +2069,10 @@ void CHyprOpenGLImpl::setMonitorTransformEnabled(bool enabled) { uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) { if (g_pHyprRenderer->isNvidia()) - return DRM_FORMAT_XRGB8888; - - if (pMonitor->drmFormat == DRM_FORMAT_XRGB8888) return DRM_FORMAT_XBGR8888; - if (pMonitor->drmFormat == DRM_FORMAT_XBGR8888) - return DRM_FORMAT_XRGB8888; + + if (pMonitor->drmFormat == DRM_FORMAT_XRGB8888 || pMonitor->drmFormat == DRM_FORMAT_XBGR8888) + return DRM_FORMAT_XBGR8888; if (pMonitor->drmFormat == DRM_FORMAT_XRGB2101010 || pMonitor->drmFormat == DRM_FORMAT_XBGR2101010) return DRM_FORMAT_XBGR2101010; return DRM_FORMAT_INVALID; diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 2830870b..c3726575 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -179,6 +179,10 @@ class CHyprOpenGLImpl { PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = nullptr; } m_sProc; + struct { + bool EXT_read_format_bgra = false; + } m_sExts; + private: std::list m_lBuffers; std::list m_lTextures; From 59cb0e20def602c0fe928c40f8398daa7ea1427d Mon Sep 17 00:00:00 2001 From: dranull <150595692+dranull@users.noreply.github.com> Date: Sun, 3 Dec 2023 12:53:12 +0000 Subject: [PATCH 324/513] input: Handle fullscreen windows in vectorToWindowIdeal (#4021) --- src/Compositor.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index a842bb6b..a12fabf1 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -701,26 +701,29 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos, CWindow* pIgnoreW } } + const int64_t WORKSPACEID = special ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace; + const auto PWORKSPACE = getWorkspaceByID(WORKSPACEID); + + if (PWORKSPACE->m_bHasFullscreenWindow) + return getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID); + // for windows, we need to check their extensions too, first. for (auto& w : m_vWindows) { if (special != isWorkspaceSpecial(w->m_iWorkspaceID)) continue; - const int64_t WORKSPACEID = special ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace; - if (!w->m_bIsX11 && !w->m_bIsFloating && w->m_bIsMapped && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_bNoFocus && w.get() != pIgnoreWindow) { - if ((w)->hasPopupAt(pos)) + if (w->hasPopupAt(pos)) return w.get(); } } + for (auto& w : m_vWindows) { if (special != isWorkspaceSpecial(w->m_iWorkspaceID)) continue; - const int64_t WORKSPACEID = special ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace; - - CBox box = {w->m_vPosition.x, w->m_vPosition.y, w->m_vSize.x, w->m_vSize.y}; + CBox box = {w->m_vPosition, w->m_vSize}; if (!w->m_bIsFloating && w->m_bIsMapped && box.containsPoint(pos) && w->m_iWorkspaceID == WORKSPACEID && !w->isHidden() && !w->m_bX11ShouldntFocus && !w->m_bNoFocus && w.get() != pIgnoreWindow) return w.get(); From dc2082b00ac0a477df32dd75a32a2a0d8ad71c90 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 3 Dec 2023 19:06:51 +0000 Subject: [PATCH 325/513] screencopy: fix transformed on shm --- src/protocols/Screencopy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 6c7178c0..0913f02e 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -449,7 +449,7 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* return false; } - CBox monbox = CBox{0, 0, frame->pMonitor->vecPixelSize.x, frame->pMonitor->vecPixelSize.y}.translate({-frame->box.x, -frame->box.y}); + CBox monbox = CBox{0, 0, frame->pMonitor->vecTransformedSize.x, frame->pMonitor->vecTransformedSize.y}.translate({-frame->box.x, -frame->box.y}); g_pHyprOpenGL->setMonitorTransformEnabled(false); g_pHyprOpenGL->renderTexture(sourceTex, &monbox, 1); g_pHyprOpenGL->setMonitorTransformEnabled(true); From e496b0f250139b572307d048f3189aa6dde72f18 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 3 Dec 2023 22:04:07 +0000 Subject: [PATCH 326/513] screencopy: fix detecting gl shm formats ref #4029 --- src/protocols/Screencopy.cpp | 27 ++- src/protocols/ToplevelExport.cpp | 16 +- src/protocols/ToplevelExportWlrFuncs.hpp | 293 +++++++++-------------- src/render/OpenGL.cpp | 135 ++++++++++- 4 files changed, 278 insertions(+), 193 deletions(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 0913f02e..19744ac5 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -210,6 +210,7 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r PFRAME->client = PCLIENT; PCLIENT->ref++; + g_pHyprRenderer->makeEGLCurrent(); PFRAME->shmFormat = g_pHyprOpenGL->getPreferredReadFormat(PFRAME->pMonitor); if (PFRAME->shmFormat == DRM_FORMAT_INVALID) { Debug::log(ERR, "No format supported by renderer in capture output"); @@ -241,7 +242,7 @@ void CScreencopyProtocolManager::captureOutput(wl_client* client, wl_resource* r wlr_output_effective_resolution(PFRAME->pMonitor->output, &ow, &oh); PFRAME->box.transform(PFRAME->pMonitor->transform, ow, oh).scale(PFRAME->pMonitor->scale).round(); - PFRAME->shmStride = (PSHMINFO->bpp / 8) * PFRAME->box.width; + PFRAME->shmStride = pixel_format_info_min_stride(PSHMINFO, PFRAME->box.w); zwlr_screencopy_frame_v1_send_buffer(PFRAME->resource, convert_drm_format_to_wl_shm(PFRAME->shmFormat), PFRAME->box.width, PFRAME->box.height, PFRAME->shmStride); @@ -456,8 +457,13 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.m_iFb); - const auto GLFORMAT = drmFormatToGL(frame->pMonitor->drmFormat); - const auto GLTYPE = glFormatToType(GLFORMAT); + GLint glf, glt; + glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glf); + glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glt); + if (glf == 0 || glt == 0) { + glf = drmFormatToGL(frame->pMonitor->drmFormat); + glt = glFormatToType(glf); + } g_pHyprRenderer->endRender(); @@ -465,7 +471,20 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* g_pHyprOpenGL->m_RenderData.pMonitor = frame->pMonitor; fb.bind(); - glReadPixels(0, 0, frame->box.w, frame->box.h, GL_RGBA, GLTYPE, data); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + const auto FMT = g_pHyprOpenGL->getPreferredReadFormat(frame->pMonitor); + const wlr_pixel_format_info* drmFmtWlr = drm_get_pixel_format_info(FMT); + uint32_t packStride = pixel_format_info_min_stride(drmFmtWlr, frame->box.w); + + if (packStride == stride) { + glReadPixels(frame->box.x, frame->box.y, frame->box.w, frame->box.h, glf, glt, data); + } else { + for (size_t i = 0; i < frame->box.h; ++i) { + uint32_t y = frame->box.x + i; + glReadPixels(frame->box.x, y, frame->box.w, 1, glf, glt, ((unsigned char*)data) + i * stride); + } + } g_pHyprOpenGL->m_RenderData.pMonitor = nullptr; diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index d68aa616..73c3ab06 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -177,6 +177,7 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou const auto PMONITOR = g_pCompositor->getMonitorFromID(PFRAME->pWindow->m_iMonitorID); + g_pHyprRenderer->makeEGLCurrent(); PFRAME->shmFormat = g_pHyprOpenGL->getPreferredReadFormat(PFRAME->pMonitor); if (PFRAME->shmFormat == DRM_FORMAT_INVALID) { Debug::log(ERR, "No format supported by renderer in capture toplevel"); @@ -204,7 +205,7 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou wlr_output_effective_resolution(PMONITOR->output, &ow, &oh); PFRAME->box.transform(PMONITOR->transform, ow, oh).round(); - PFRAME->shmStride = (PSHMINFO->bpp / 8) * PFRAME->box.width; + PFRAME->shmStride = pixel_format_info_min_stride(PSHMINFO, PFRAME->box.w); hyprland_toplevel_export_frame_v1_send_buffer(PFRAME->resource, convert_drm_format_to_wl_shm(PFRAME->shmFormat), PFRAME->box.width, PFRAME->box.height, PFRAME->shmStride); @@ -386,12 +387,19 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times if (frame->overlayCursor) g_pHyprRenderer->renderSoftwareCursors(PMONITOR, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.vec()); - const auto GLFORMAT = drmFormatToGL(frame->pMonitor->drmFormat); - const auto GLTYPE = glFormatToType(GLFORMAT); + GLint glf, glt; + glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glf); + glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glt); + if (glf == 0 || glt == 0) { + glf = drmFormatToGL(frame->pMonitor->drmFormat); + glt = glFormatToType(glf); + } g_pHyprOpenGL->m_RenderData.mainFB->bind(); - glReadPixels(0, 0, frame->box.width, frame->box.height, GL_RGBA, GLTYPE, data); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + + glReadPixels(0, 0, frame->box.width, frame->box.height, glf, glt, data); g_pHyprRenderer->endRender(); diff --git a/src/protocols/ToplevelExportWlrFuncs.hpp b/src/protocols/ToplevelExportWlrFuncs.hpp index b580d3f0..b6f387e8 100644 --- a/src/protocols/ToplevelExportWlrFuncs.hpp +++ b/src/protocols/ToplevelExportWlrFuncs.hpp @@ -11,8 +11,10 @@ struct wlr_pixel_format_info { */ uint32_t opaque_substitute; - /* Bits per pixels */ - uint32_t bpp; + /* Bytes per block (including padding) */ + uint32_t bytes_per_block; + /* Size of a block in pixels (zero for 1×1) */ + uint32_t block_width, block_height; /* True if the format has an alpha channel */ bool has_alpha; @@ -20,143 +22,171 @@ struct wlr_pixel_format_info { static const struct wlr_pixel_format_info pixel_format_info[] = { { - .drm_format = DRM_FORMAT_XRGB8888, - .opaque_substitute = DRM_FORMAT_INVALID, - .bpp = 32, - .has_alpha = false, + .drm_format = DRM_FORMAT_XRGB8888, + .bytes_per_block = 4, }, { .drm_format = DRM_FORMAT_ARGB8888, .opaque_substitute = DRM_FORMAT_XRGB8888, - .bpp = 32, + .bytes_per_block = 4, .has_alpha = true, }, { - .drm_format = DRM_FORMAT_XBGR8888, - .opaque_substitute = DRM_FORMAT_INVALID, - .bpp = 32, - .has_alpha = false, + .drm_format = DRM_FORMAT_XBGR8888, + .bytes_per_block = 4, }, { .drm_format = DRM_FORMAT_ABGR8888, .opaque_substitute = DRM_FORMAT_XBGR8888, - .bpp = 32, + .bytes_per_block = 4, .has_alpha = true, }, { - .drm_format = DRM_FORMAT_RGBX8888, - .opaque_substitute = DRM_FORMAT_INVALID, - .bpp = 32, - .has_alpha = false, + .drm_format = DRM_FORMAT_RGBX8888, + .bytes_per_block = 4, }, { .drm_format = DRM_FORMAT_RGBA8888, .opaque_substitute = DRM_FORMAT_RGBX8888, - .bpp = 32, + .bytes_per_block = 4, .has_alpha = true, }, { - .drm_format = DRM_FORMAT_BGRX8888, - .opaque_substitute = DRM_FORMAT_INVALID, - .bpp = 32, - .has_alpha = false, + .drm_format = DRM_FORMAT_BGRX8888, + .bytes_per_block = 4, }, { .drm_format = DRM_FORMAT_BGRA8888, .opaque_substitute = DRM_FORMAT_BGRX8888, - .bpp = 32, + .bytes_per_block = 4, .has_alpha = true, }, { - .drm_format = DRM_FORMAT_BGR888, - .opaque_substitute = DRM_FORMAT_INVALID, - .bpp = 24, - .has_alpha = false, + .drm_format = DRM_FORMAT_R8, + .bytes_per_block = 1, }, { - .drm_format = DRM_FORMAT_RGBX4444, - .opaque_substitute = DRM_FORMAT_INVALID, - .bpp = 16, - .has_alpha = false, + .drm_format = DRM_FORMAT_GR88, + .bytes_per_block = 2, + }, + { + .drm_format = DRM_FORMAT_RGB888, + .bytes_per_block = 3, + }, + { + .drm_format = DRM_FORMAT_BGR888, + .bytes_per_block = 3, + }, + { + .drm_format = DRM_FORMAT_RGBX4444, + .bytes_per_block = 2, }, { .drm_format = DRM_FORMAT_RGBA4444, .opaque_substitute = DRM_FORMAT_RGBX4444, - .bpp = 16, + .bytes_per_block = 2, .has_alpha = true, }, { - .drm_format = DRM_FORMAT_RGBX5551, - .opaque_substitute = DRM_FORMAT_INVALID, - .bpp = 16, - .has_alpha = false, + .drm_format = DRM_FORMAT_BGRX4444, + .bytes_per_block = 2, + }, + { + .drm_format = DRM_FORMAT_BGRA4444, + .opaque_substitute = DRM_FORMAT_BGRX4444, + .bytes_per_block = 2, + .has_alpha = true, + }, + { + .drm_format = DRM_FORMAT_RGBX5551, + .bytes_per_block = 2, }, { .drm_format = DRM_FORMAT_RGBA5551, .opaque_substitute = DRM_FORMAT_RGBX5551, - .bpp = 16, + .bytes_per_block = 2, .has_alpha = true, }, { - .drm_format = DRM_FORMAT_RGB565, - .opaque_substitute = DRM_FORMAT_INVALID, - .bpp = 16, - .has_alpha = false, + .drm_format = DRM_FORMAT_BGRX5551, + .bytes_per_block = 2, }, { - .drm_format = DRM_FORMAT_BGR565, - .opaque_substitute = DRM_FORMAT_INVALID, - .bpp = 16, - .has_alpha = false, + .drm_format = DRM_FORMAT_BGRA5551, + .opaque_substitute = DRM_FORMAT_BGRX5551, + .bytes_per_block = 2, + .has_alpha = true, }, { - .drm_format = DRM_FORMAT_XRGB2101010, - .opaque_substitute = DRM_FORMAT_INVALID, - .bpp = 32, - .has_alpha = false, + .drm_format = DRM_FORMAT_XRGB1555, + .bytes_per_block = 2, + }, + { + .drm_format = DRM_FORMAT_ARGB1555, + .opaque_substitute = DRM_FORMAT_XRGB1555, + .bytes_per_block = 2, + .has_alpha = true, + }, + { + .drm_format = DRM_FORMAT_RGB565, + .bytes_per_block = 2, + }, + { + .drm_format = DRM_FORMAT_BGR565, + .bytes_per_block = 2, + }, + { + .drm_format = DRM_FORMAT_XRGB2101010, + .bytes_per_block = 4, }, { .drm_format = DRM_FORMAT_ARGB2101010, .opaque_substitute = DRM_FORMAT_XRGB2101010, - .bpp = 32, + .bytes_per_block = 4, .has_alpha = true, }, { - .drm_format = DRM_FORMAT_XBGR2101010, - .opaque_substitute = DRM_FORMAT_INVALID, - .bpp = 32, - .has_alpha = false, + .drm_format = DRM_FORMAT_XBGR2101010, + .bytes_per_block = 4, }, { .drm_format = DRM_FORMAT_ABGR2101010, .opaque_substitute = DRM_FORMAT_XBGR2101010, - .bpp = 32, + .bytes_per_block = 4, .has_alpha = true, }, { - .drm_format = DRM_FORMAT_XBGR16161616F, - .opaque_substitute = DRM_FORMAT_INVALID, - .bpp = 64, - .has_alpha = false, + .drm_format = DRM_FORMAT_XBGR16161616F, + .bytes_per_block = 8, }, { .drm_format = DRM_FORMAT_ABGR16161616F, .opaque_substitute = DRM_FORMAT_XBGR16161616F, - .bpp = 64, + .bytes_per_block = 8, .has_alpha = true, }, { - .drm_format = DRM_FORMAT_XBGR16161616, - .opaque_substitute = DRM_FORMAT_INVALID, - .bpp = 64, - .has_alpha = false, + .drm_format = DRM_FORMAT_XBGR16161616, + .bytes_per_block = 8, }, { .drm_format = DRM_FORMAT_ABGR16161616, .opaque_substitute = DRM_FORMAT_XBGR16161616, - .bpp = 64, + .bytes_per_block = 8, .has_alpha = true, }, + { + .drm_format = DRM_FORMAT_YVYU, + .bytes_per_block = 4, + .block_width = 2, + .block_height = 1, + }, + { + .drm_format = DRM_FORMAT_VYUY, + .bytes_per_block = 4, + .block_width = 2, + .block_height = 1, + }, }; static const size_t pixel_format_info_size = sizeof(pixel_format_info) / sizeof(pixel_format_info[0]); @@ -187,124 +217,27 @@ static enum wl_shm_format convert_drm_format_to_wl_shm(uint32_t fmt) { } } -struct wlr_gles2_pixel_format { - uint32_t drm_format; - // optional field, if empty then internalformat = format - GLint gl_internalformat; - GLint gl_format, gl_type; - bool has_alpha; -}; +static uint32_t pixel_format_info_pixels_per_block(const struct wlr_pixel_format_info* info) { + uint32_t pixels = info->block_width * info->block_height; + return pixels > 0 ? pixels : 1; +} -static const struct wlr_gles2_pixel_format formats[] = { - { - .drm_format = DRM_FORMAT_ARGB8888, - .gl_format = GL_BGRA_EXT, - .gl_type = GL_UNSIGNED_BYTE, - .has_alpha = true, - }, - { - .drm_format = DRM_FORMAT_XRGB8888, - .gl_format = GL_BGRA_EXT, - .gl_type = GL_UNSIGNED_BYTE, - .has_alpha = false, - }, - { - .drm_format = DRM_FORMAT_XBGR8888, - .gl_format = GL_RGBA, - .gl_type = GL_UNSIGNED_BYTE, - .has_alpha = false, - }, - { - .drm_format = DRM_FORMAT_ABGR8888, - .gl_format = GL_RGBA, - .gl_type = GL_UNSIGNED_BYTE, - .has_alpha = true, - }, - { - .drm_format = DRM_FORMAT_BGR888, - .gl_format = GL_RGB, - .gl_type = GL_UNSIGNED_BYTE, - .has_alpha = false, - }, -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - { - .drm_format = DRM_FORMAT_RGBX4444, - .gl_format = GL_RGBA, - .gl_type = GL_UNSIGNED_SHORT_4_4_4_4, - .has_alpha = false, - }, - { - .drm_format = DRM_FORMAT_RGBA4444, - .gl_format = GL_RGBA, - .gl_type = GL_UNSIGNED_SHORT_4_4_4_4, - .has_alpha = true, - }, - { - .drm_format = DRM_FORMAT_RGBX5551, - .gl_format = GL_RGBA, - .gl_type = GL_UNSIGNED_SHORT_5_5_5_1, - .has_alpha = false, - }, - { - .drm_format = DRM_FORMAT_RGBA5551, - .gl_format = GL_RGBA, - .gl_type = GL_UNSIGNED_SHORT_5_5_5_1, - .has_alpha = true, - }, - { - .drm_format = DRM_FORMAT_RGB565, - .gl_format = GL_RGB, - .gl_type = GL_UNSIGNED_SHORT_5_6_5, - .has_alpha = false, - }, - { - .drm_format = DRM_FORMAT_XBGR2101010, - .gl_format = GL_RGBA, - .gl_type = GL_UNSIGNED_INT_2_10_10_10_REV_EXT, - .has_alpha = false, - }, - { - .drm_format = DRM_FORMAT_ABGR2101010, - .gl_format = GL_RGBA, - .gl_type = GL_UNSIGNED_INT_2_10_10_10_REV_EXT, - .has_alpha = true, - }, - { - .drm_format = DRM_FORMAT_XBGR16161616F, - .gl_format = GL_RGBA, - .gl_type = GL_HALF_FLOAT_OES, - .has_alpha = false, - }, - { - .drm_format = DRM_FORMAT_ABGR16161616F, - .gl_format = GL_RGBA, - .gl_type = GL_HALF_FLOAT_OES, - .has_alpha = true, - }, - { - .drm_format = DRM_FORMAT_XBGR16161616, - .gl_internalformat = GL_RGBA16_EXT, - .gl_format = GL_RGBA, - .gl_type = GL_UNSIGNED_SHORT, - .has_alpha = false, - }, - { - .drm_format = DRM_FORMAT_ABGR16161616, - .gl_internalformat = GL_RGBA16_EXT, - .gl_format = GL_RGBA, - .gl_type = GL_UNSIGNED_SHORT, - .has_alpha = true, - }, -#endif -}; - -inline const struct wlr_gles2_pixel_format* gles2FromDRM(uint32_t fmt) { - for (size_t i = 0; i < sizeof(formats) / sizeof(*formats); ++i) { - if (formats[i].drm_format == fmt) { - return &formats[i]; - } +static int32_t div_round_up(int32_t dividend, int32_t divisor) { + int32_t quotient = dividend / divisor; + if (dividend % divisor != 0) { + quotient++; } - return NULL; + return quotient; +} + +static int32_t pixel_format_info_min_stride(const wlr_pixel_format_info* fmt, int32_t width) { + int32_t pixels_per_block = (int32_t)pixel_format_info_pixels_per_block(fmt); + int32_t bytes_per_block = (int32_t)fmt->bytes_per_block; + if (width > INT32_MAX / bytes_per_block) { + wlr_log(WLR_DEBUG, "Invalid width %d (overflow)", width); + return 0; + } + return div_round_up(width * bytes_per_block, pixels_per_block); } #endif \ No newline at end of file diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index cbfe56e8..061cc2b5 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2067,13 +2067,138 @@ void CHyprOpenGLImpl::setMonitorTransformEnabled(bool enabled) { m_bEndFrame = !enabled; } +struct SGLPixelFormat { + uint32_t drmFormat = DRM_FORMAT_INVALID; + GLint glInternalFormat = 0; + GLint glFormat = 0; + GLint glType = 0; + bool withAlpha = false; +}; + +inline const SGLPixelFormat GLES2_FORMATS[] = { + { + .drmFormat = DRM_FORMAT_ARGB8888, + .glFormat = GL_BGRA_EXT, + .glType = GL_UNSIGNED_BYTE, + .withAlpha = true, + }, + { + .drmFormat = DRM_FORMAT_XRGB8888, + .glFormat = GL_BGRA_EXT, + .glType = GL_UNSIGNED_BYTE, + .withAlpha = false, + }, + { + .drmFormat = DRM_FORMAT_XBGR8888, + .glFormat = GL_RGBA, + .glType = GL_UNSIGNED_BYTE, + .withAlpha = false, + }, + { + .drmFormat = DRM_FORMAT_ABGR8888, + .glFormat = GL_RGBA, + .glType = GL_UNSIGNED_BYTE, + .withAlpha = true, + }, + { + .drmFormat = DRM_FORMAT_BGR888, + .glFormat = GL_RGB, + .glType = GL_UNSIGNED_BYTE, + .withAlpha = false, + }, +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + { + .drmFormat = DRM_FORMAT_RGBX4444, + .glFormat = GL_RGBA, + .glType = GL_UNSIGNED_SHORT_4_4_4_4, + .withAlpha = false, + }, + { + .drmFormat = DRM_FORMAT_RGBA4444, + .glFormat = GL_RGBA, + .glType = GL_UNSIGNED_SHORT_4_4_4_4, + .withAlpha = true, + }, + { + .drmFormat = DRM_FORMAT_RGBX5551, + .glFormat = GL_RGBA, + .glType = GL_UNSIGNED_SHORT_5_5_5_1, + .withAlpha = false, + }, + { + .drmFormat = DRM_FORMAT_RGBA5551, + .glFormat = GL_RGBA, + .glType = GL_UNSIGNED_SHORT_5_5_5_1, + .withAlpha = true, + }, + { + .drmFormat = DRM_FORMAT_RGB565, + .glFormat = GL_RGB, + .glType = GL_UNSIGNED_SHORT_5_6_5, + .withAlpha = false, + }, + { + .drmFormat = DRM_FORMAT_XBGR2101010, + .glFormat = GL_RGBA, + .glType = GL_UNSIGNED_INT_2_10_10_10_REV_EXT, + .withAlpha = false, + }, + { + .drmFormat = DRM_FORMAT_ABGR2101010, + .glFormat = GL_RGBA, + .glType = GL_UNSIGNED_INT_2_10_10_10_REV_EXT, + .withAlpha = true, + }, + { + .drmFormat = DRM_FORMAT_XBGR16161616F, + .glFormat = GL_RGBA, + .glType = GL_HALF_FLOAT_OES, + .withAlpha = false, + }, + { + .drmFormat = DRM_FORMAT_ABGR16161616F, + .glFormat = GL_RGBA, + .glType = GL_HALF_FLOAT_OES, + .withAlpha = true, + }, + { + .drmFormat = DRM_FORMAT_XBGR16161616, + .glInternalFormat = GL_RGBA16_EXT, + .glFormat = GL_RGBA, + .glType = GL_UNSIGNED_SHORT, + .withAlpha = false, + }, + { + .drmFormat = DRM_FORMAT_ABGR16161616, + .glInternalFormat = GL_RGBA16_EXT, + .glFormat = GL_RGBA, + .glType = GL_UNSIGNED_SHORT, + .withAlpha = true, + }, +#endif +}; + uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) { if (g_pHyprRenderer->isNvidia()) return DRM_FORMAT_XBGR8888; - if (pMonitor->drmFormat == DRM_FORMAT_XRGB8888 || pMonitor->drmFormat == DRM_FORMAT_XBGR8888) - return DRM_FORMAT_XBGR8888; - if (pMonitor->drmFormat == DRM_FORMAT_XRGB2101010 || pMonitor->drmFormat == DRM_FORMAT_XBGR2101010) - return DRM_FORMAT_XBGR2101010; - return DRM_FORMAT_INVALID; + GLint glf = -1, glt = -1, as = -1; + glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glf); + glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glt); + glGetIntegerv(GL_ALPHA_BITS, &as); + + if (glf == 0 || glt == 0) { + glf = drmFormatToGL(pMonitor->drmFormat); + glt = glFormatToType(glf); + } + + for (auto& fmt : GLES2_FORMATS) { + if (fmt.glFormat == glf && fmt.glType == glt && fmt.withAlpha == (as > 0)) + return fmt.drmFormat; + } + + if (m_sExts.EXT_read_format_bgra) + return DRM_FORMAT_XRGB8888; + + return DRM_FORMAT_XBGR8888; } From 9a9528d09375e6017088af354799ac381b939c1f Mon Sep 17 00:00:00 2001 From: dranull <150595692+dranull@users.noreply.github.com> Date: Mon, 4 Dec 2023 01:35:24 +0000 Subject: [PATCH 327/513] config: Minor --config improvements, fixes (#4034) * Follow symlink, only file, absolute path for -c * Create config file only for default paths * Skip non-file source= glob results * Check for absolute path on XDG_CONFIG_HOME As per spec, all non-absolute paths should be ignored. https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html --- src/config/ConfigManager.cpp | 40 ++++++++++++++++++++---------------- src/main.cpp | 9 +++++--- 2 files changed, 28 insertions(+), 21 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 5659667e..41248d08 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -48,12 +48,11 @@ CConfigManager::CConfigManager() { std::string CConfigManager::getConfigDir() { static const char* xdgConfigHome = getenv("XDG_CONFIG_HOME"); - std::string configPath; - if (!xdgConfigHome) - configPath = getenv("HOME") + std::string("/.config"); - else - configPath = xdgConfigHome; - return configPath; + + if (xdgConfigHome && std::filesystem::path(xdgConfigHome).is_absolute()) + return xdgConfigHome; + + return getenv("HOME") + std::string("/.config"); } std::string CConfigManager::getMainConfigPath() { @@ -1263,7 +1262,12 @@ void CConfigManager::handleSource(const std::string& command, const std::string& for (size_t i = 0; i < glob_buf->gl_pathc; i++) { auto value = absolutePath(glob_buf->gl_pathv[i], configCurrentPath); - if (!std::filesystem::exists(value)) { + if (!std::filesystem::is_regular_file(value)) { + if (std::filesystem::exists(value)) { + Debug::log(WARN, "source= skipping non-file {}", value); + continue; + } + Debug::log(ERR, "source= file doesnt exist"); parseError = "source file " + value + " doesn't exist!"; return; @@ -1570,20 +1574,20 @@ void CConfigManager::loadConfigLoadVars() { std::string mainConfigPath = getMainConfigPath(); Debug::log(LOG, "Using config: {}", mainConfigPath); configPaths.push_back(mainConfigPath); - std::string configPath = mainConfigPath.substr(0, mainConfigPath.find_last_of('/')); - // find_last_of never returns npos since main_config at least has /hypr/ - if (!std::filesystem::is_directory(configPath)) { - Debug::log(WARN, "Creating config home directory"); - try { - std::filesystem::create_directories(configPath); - } catch (...) { - parseError = "Broken config file! (Could not create config directory)"; - return; + if (g_pCompositor->explicitConfigPath.empty() && !std::filesystem::exists(mainConfigPath)) { + std::string configPath = std::filesystem::path(mainConfigPath).parent_path(); + + if (!std::filesystem::is_directory(configPath)) { + Debug::log(WARN, "Creating config home directory"); + try { + std::filesystem::create_directories(configPath); + } catch (...) { + parseError = "Broken config file! (Could not create config directory)"; + return; + } } - } - if (!std::filesystem::exists(mainConfigPath)) { Debug::log(WARN, "No config file found; attempting to generate."); std::ofstream ofs; ofs.open(mainConfigPath, std::ios::trunc); diff --git a/src/main.cpp b/src/main.cpp index 27a768ba..0f68c3b2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,14 +54,17 @@ int main(int argc, char** argv) { } std::string next_arg = std::next(it)->c_str(); - if (!std::filesystem::exists(next_arg)) { - std::cerr << "[ ERROR ] Config path '" << next_arg << "' doesn't exist!\n"; + if (std::filesystem::is_symlink(next_arg)) + next_arg = std::filesystem::read_symlink(next_arg); + + if (!std::filesystem::is_regular_file(next_arg)) { + std::cerr << "[ ERROR ] Config file '" << next_arg << "' doesn't exist!\n"; help(); return 1; } - configPath = next_arg; + configPath = std::filesystem::weakly_canonical(next_arg); Debug::log(LOG, "User-specified config location: '{}'", configPath); it++; From 45d3fbb8d8409b2def531a9315916606165875cf Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 4 Dec 2023 01:44:06 +0000 Subject: [PATCH 328/513] opengl: free window framebuffers in ~dtor ref #4036 --- src/Compositor.cpp | 3 --- src/Window.cpp | 3 +++ src/protocols/Screencopy.cpp | 2 +- src/protocols/ToplevelExport.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index a12fabf1..3020b96d 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1395,14 +1395,11 @@ void CCompositor::cleanupFadingOut(const int& monid) { if (valid && !w->m_bReadyToDelete) continue; - std::erase_if(g_pHyprOpenGL->m_mWindowFramebuffers, [&](const auto& other) { return other.first == w; }); w->m_bFadingOut = false; removeWindowFromVectorSafe(w); std::erase(m_vWindowsFadingOut, w); Debug::log(LOG, "Cleanup: destroyed a window"); - - glFlush(); // to free mem NOW. return; } } diff --git a/src/Window.cpp b/src/Window.cpp index 7569c869..bcb819a8 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -21,6 +21,9 @@ CWindow::~CWindow() { g_pCompositor->m_pLastFocus = nullptr; g_pCompositor->m_pLastWindow = nullptr; } + + g_pHyprRenderer->makeEGLCurrent(); + std::erase_if(g_pHyprOpenGL->m_mWindowFramebuffers, [&](const auto& other) { return other.first == this; }); } SWindowDecorationExtents CWindow::getFullWindowExtents() { diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 19744ac5..65f50893 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -442,7 +442,7 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* g_pHyprRenderer->makeEGLCurrent(); CFramebuffer fb; - fb.alloc(frame->box.w, frame->box.h, frame->pMonitor->drmFormat); + fb.alloc(frame->box.w, frame->box.h, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : frame->pMonitor->drmFormat); if (!g_pHyprRenderer->beginRender(frame->pMonitor, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &fb)) { wlr_texture_destroy(sourceTex); diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 73c3ab06..6a001c02 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -367,7 +367,7 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times g_pHyprRenderer->makeEGLCurrent(); CFramebuffer outFB; - outFB.alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, PMONITOR->drmFormat); + outFB.alloc(PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, g_pHyprRenderer->isNvidia() ? DRM_FORMAT_XBGR8888 : PMONITOR->drmFormat); if (!g_pHyprRenderer->beginRender(PMONITOR, fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &outFB)) { wlr_buffer_end_data_ptr_access(frame->buffer); From 5d100bdcbbd87bac74935eae6b7d7aed25620323 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 4 Dec 2023 02:08:34 +0000 Subject: [PATCH 329/513] opengl: clear layer fade fbs in ~dtor --- src/Compositor.cpp | 3 --- src/helpers/WLClasses.cpp | 5 +++++ src/helpers/WLClasses.hpp | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 3020b96d..9419583e 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1441,9 +1441,6 @@ void CCompositor::cleanupFadingOut(const int& monid) { g_pHyprOpenGL->markBlurDirtyForMonitor(getMonitorFromID(monid)); if (ls->fadingOut && ls->readyToDelete && !ls->alpha.isBeingAnimated()) { - g_pHyprOpenGL->m_mLayerFramebuffers[ls].release(); - g_pHyprOpenGL->m_mLayerFramebuffers.erase(ls); - for (auto& m : m_vMonitors) { for (auto& lsl : m->m_aLayerSurfaceLayers) { if (!lsl.empty() && std::find_if(lsl.begin(), lsl.end(), [&](std::unique_ptr& other) { return other.get() == ls; }) != lsl.end()) { diff --git a/src/helpers/WLClasses.cpp b/src/helpers/WLClasses.cpp index 6923d6a5..9a326614 100644 --- a/src/helpers/WLClasses.cpp +++ b/src/helpers/WLClasses.cpp @@ -8,6 +8,11 @@ SLayerSurface::SLayerSurface() { alpha.registerVar(); } +SLayerSurface::~SLayerSurface() { + g_pHyprRenderer->makeEGLCurrent(); + std::erase_if(g_pHyprOpenGL->m_mLayerFramebuffers, [&](const auto& other) { return other.first == this; }); +} + void SLayerSurface::applyRules() { noAnimations = false; forceBlur = false; diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index f7efbe98..d381fa0d 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -16,6 +16,7 @@ struct SLayerRule { struct SLayerSurface { SLayerSurface(); + ~SLayerSurface(); void applyRules(); From 68783d904d850df65887adb1bab7eff59943c1ac Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 4 Dec 2023 03:52:54 +0000 Subject: [PATCH 330/513] screencopy: use buffer format for glReadPixels fixes #4029 --- src/protocols/Screencopy.cpp | 19 +++---- src/protocols/ToplevelExport.cpp | 13 ++--- src/render/OpenGL.cpp | 20 +++---- src/render/OpenGL.hpp | 95 +++++++++++++++++--------------- 4 files changed, 76 insertions(+), 71 deletions(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 65f50893..e5aaab62 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -457,12 +457,12 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.m_iFb); - GLint glf, glt; - glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glf); - glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glt); - if (glf == 0 || glt == 0) { - glf = drmFormatToGL(frame->pMonitor->drmFormat); - glt = glFormatToType(glf); + const auto PFORMAT = g_pHyprOpenGL->getPixelFormatFromDRM(format); + if (!PFORMAT) { + g_pHyprRenderer->endRender(); + wlr_texture_destroy(sourceTex); + wlr_buffer_end_data_ptr_access(frame->buffer); + return false; } g_pHyprRenderer->endRender(); @@ -473,16 +473,15 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* glPixelStorei(GL_PACK_ALIGNMENT, 1); - const auto FMT = g_pHyprOpenGL->getPreferredReadFormat(frame->pMonitor); - const wlr_pixel_format_info* drmFmtWlr = drm_get_pixel_format_info(FMT); + const wlr_pixel_format_info* drmFmtWlr = drm_get_pixel_format_info(format); uint32_t packStride = pixel_format_info_min_stride(drmFmtWlr, frame->box.w); if (packStride == stride) { - glReadPixels(frame->box.x, frame->box.y, frame->box.w, frame->box.h, glf, glt, data); + glReadPixels(frame->box.x, frame->box.y, frame->box.w, frame->box.h, PFORMAT->glFormat, PFORMAT->glType, data); } else { for (size_t i = 0; i < frame->box.h; ++i) { uint32_t y = frame->box.x + i; - glReadPixels(frame->box.x, y, frame->box.w, 1, glf, glt, ((unsigned char*)data) + i * stride); + glReadPixels(frame->box.x, y, frame->box.w, 1, PFORMAT->glFormat, PFORMAT->glType, ((unsigned char*)data) + i * stride); } } diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 6a001c02..dabad2ab 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -387,19 +387,18 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times if (frame->overlayCursor) g_pHyprRenderer->renderSoftwareCursors(PMONITOR, fakeDamage, g_pInputManager->getMouseCoordsInternal() - frame->pWindow->m_vRealPosition.vec()); - GLint glf, glt; - glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glf); - glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glt); - if (glf == 0 || glt == 0) { - glf = drmFormatToGL(frame->pMonitor->drmFormat); - glt = glFormatToType(glf); + const auto PFORMAT = g_pHyprOpenGL->getPixelFormatFromDRM(format); + if (!PFORMAT) { + g_pHyprRenderer->endRender(); + wlr_buffer_end_data_ptr_access(frame->buffer); + return false; } g_pHyprOpenGL->m_RenderData.mainFB->bind(); glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(0, 0, frame->box.width, frame->box.height, glf, glt, data); + glReadPixels(0, 0, frame->box.width, frame->box.height, PFORMAT->glFormat, PFORMAT->glType, data); g_pHyprRenderer->endRender(); diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 061cc2b5..2c9151e5 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2067,14 +2067,6 @@ void CHyprOpenGLImpl::setMonitorTransformEnabled(bool enabled) { m_bEndFrame = !enabled; } -struct SGLPixelFormat { - uint32_t drmFormat = DRM_FORMAT_INVALID; - GLint glInternalFormat = 0; - GLint glFormat = 0; - GLint glType = 0; - bool withAlpha = false; -}; - inline const SGLPixelFormat GLES2_FORMATS[] = { { .drmFormat = DRM_FORMAT_ARGB8888, @@ -2179,9 +2171,6 @@ inline const SGLPixelFormat GLES2_FORMATS[] = { }; uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) { - if (g_pHyprRenderer->isNvidia()) - return DRM_FORMAT_XBGR8888; - GLint glf = -1, glt = -1, as = -1; glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &glf); glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &glt); @@ -2202,3 +2191,12 @@ uint32_t CHyprOpenGLImpl::getPreferredReadFormat(CMonitor* pMonitor) { return DRM_FORMAT_XBGR8888; } + +const SGLPixelFormat* CHyprOpenGLImpl::getPixelFormatFromDRM(uint32_t drmFormat) { + for (auto& fmt : GLES2_FORMATS) { + if (fmt.drmFormat == drmFormat) + return &fmt; + } + + return nullptr; +} \ No newline at end of file diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index c3726575..efccaad4 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -41,6 +41,14 @@ struct SRenderModifData { float scale = 1.f; }; +struct SGLPixelFormat { + uint32_t drmFormat = DRM_FORMAT_INVALID; + GLint glInternalFormat = 0; + GLint glFormat = 0; + GLint glType = 0; + bool withAlpha = false; +}; + struct SMonitorRenderData { CFramebuffer offloadFB; CFramebuffer mirrorFB; // these are used for some effects, @@ -108,66 +116,67 @@ class CHyprOpenGLImpl { public: CHyprOpenGLImpl(); - void begin(CMonitor*, CRegion*, CFramebuffer* fb = nullptr /* if provided, it's not a real frame */); - void end(); + void begin(CMonitor*, CRegion*, CFramebuffer* fb = nullptr /* if provided, it's not a real frame */); + void end(); - void renderRect(CBox*, const CColor&, int round = 0); - void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f); - void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0); - void renderTexture(wlr_texture*, CBox*, float a, int round = 0, bool allowCustomUV = false); - void renderTexture(const CTexture&, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); - void renderTextureWithBlur(const CTexture&, CBox*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); - void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0); - void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); - void renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte); + void renderRect(CBox*, const CColor&, int round = 0); + void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f); + void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0); + void renderTexture(wlr_texture*, CBox*, float a, int round = 0, bool allowCustomUV = false); + void renderTexture(const CTexture&, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); + void renderTextureWithBlur(const CTexture&, CBox*, float a, wlr_surface* pSurface, int round = 0, bool blockBlurOptimization = false, float blurA = 1.f); + void renderRoundedShadow(CBox*, int round, int range, const CColor& color, float a = 1.0); + void renderBorder(CBox*, const CGradientValueData&, int round, int borderSize, float a = 1.0, int outerRound = -1 /* use round */); + void renderTextureMatte(const CTexture& tex, CBox* pBox, CFramebuffer& matte); - void setMonitorTransformEnabled(bool enabled); + void setMonitorTransformEnabled(bool enabled); - void saveMatrix(); - void setMatrixScaleTranslate(const Vector2D& translate, const float& scale); - void restoreMatrix(); + void saveMatrix(); + void setMatrixScaleTranslate(const Vector2D& translate, const float& scale); + void restoreMatrix(); - void blend(bool enabled); + void blend(bool enabled); - void makeWindowSnapshot(CWindow*); - void makeRawWindowSnapshot(CWindow*, CFramebuffer*); - void makeLayerSnapshot(SLayerSurface*); - void renderSnapshot(CWindow**); - void renderSnapshot(SLayerSurface**); + void makeWindowSnapshot(CWindow*); + void makeRawWindowSnapshot(CWindow*, CFramebuffer*); + void makeLayerSnapshot(SLayerSurface*); + void renderSnapshot(CWindow**); + void renderSnapshot(SLayerSurface**); - void clear(const CColor&); - void clearWithTex(); - void scissor(const CBox*, bool transform = true); - void scissor(const pixman_box32*, bool transform = true); - void scissor(const int x, const int y, const int w, const int h, bool transform = true); + void clear(const CColor&); + void clearWithTex(); + void scissor(const CBox*, bool transform = true); + void scissor(const pixman_box32*, bool transform = true); + void scissor(const int x, const int y, const int w, const int h, bool transform = true); - void destroyMonitorResources(CMonitor*); + void destroyMonitorResources(CMonitor*); - void markBlurDirtyForMonitor(CMonitor*); + void markBlurDirtyForMonitor(CMonitor*); - void preWindowPass(); - bool preBlurQueued(); - void preRender(CMonitor*); + void preWindowPass(); + bool preBlurQueued(); + void preRender(CMonitor*); - void saveBufferForMirror(); - void renderMirrored(); + void saveBufferForMirror(); + void renderMirrored(); - void applyScreenShader(const std::string& path); + void applyScreenShader(const std::string& path); - void bindOffMain(); - void renderOffToMain(CFramebuffer* off); - void bindBackOnMain(); + void bindOffMain(); + void renderOffToMain(CFramebuffer* off); + void bindBackOnMain(); - uint32_t getPreferredReadFormat(CMonitor* pMonitor); + uint32_t getPreferredReadFormat(CMonitor* pMonitor); + const SGLPixelFormat* getPixelFormatFromDRM(uint32_t drmFormat); - SCurrentRenderData m_RenderData; + SCurrentRenderData m_RenderData; - GLint m_iCurrentOutputFb = 0; + GLint m_iCurrentOutputFb = 0; - bool m_bReloadScreenShader = true; // at launch it can be set + bool m_bReloadScreenShader = true; // at launch it can be set - CWindow* m_pCurrentWindow = nullptr; // hack to get the current rendered window - SLayerSurface* m_pCurrentLayer = nullptr; // hack to get the current rendered layer + CWindow* m_pCurrentWindow = nullptr; // hack to get the current rendered window + SLayerSurface* m_pCurrentLayer = nullptr; // hack to get the current rendered layer std::unordered_map m_mWindowFramebuffers; std::unordered_map m_mLayerFramebuffers; From aa46aaed04f089b849c45a077e81e8b562be23df Mon Sep 17 00:00:00 2001 From: Glizda Date: Mon, 4 Dec 2023 19:47:58 +0100 Subject: [PATCH 331/513] config: Add variables to default config (#4032) * update default config * Fix inconsistency in variable naming * continuation of last commit * edited example/hyprland.conf for parity * fix issue * deleted unwanted newline --- example/hyprland.conf | 10 +++++++--- src/config/defaultConfig.hpp | 11 ++++++++--- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/example/hyprland.conf b/example/hyprland.conf index 7560fefe..e6c2a641 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -19,6 +19,10 @@ monitor=,preferred,auto,auto # Source a file (multi-file configs) # source = ~/.config/hypr/myColors.conf +# Set programs that you use +$terminal = kitty +$fileManager = dolphin +$menu = wofi --show drun # Some default env vars. env = XCURSOR_SIZE,24 @@ -127,12 +131,12 @@ windowrulev2 = nomaximizerequest, class:.* # You'll probably like this. $mainMod = SUPER # Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more -bind = $mainMod, Q, exec, kitty +bind = $mainMod, Q, exec, $terminal bind = $mainMod, C, killactive, bind = $mainMod, M, exit, -bind = $mainMod, E, exec, dolphin +bind = $mainMod, E, exec, $fileManager bind = $mainMod, V, togglefloating, -bind = $mainMod, R, exec, wofi --show drun +bind = $mainMod, R, exec, $menu bind = $mainMod, P, pseudo, # dwindle bind = $mainMod, J, togglesplit, # dwindle diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 6a859220..22d3b332 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -28,6 +28,11 @@ monitor=,preferred,auto,auto # Source a file (multi-file configs) # source = ~/.config/hypr/myColors.conf +# Set programs that you use +$terminal = kitty +$fileManager = dolphin +$menu = wofi --show drun + # Some default env vars. env = XCURSOR_SIZE,24 @@ -134,12 +139,12 @@ windowrulev2 = nomaximizerequest, class:.* # You'll probably like this. $mainMod = SUPER # Example binds, see https://wiki.hyprland.org/Configuring/Binds/ for more -bind = $mainMod, Q, exec, kitty +bind = $mainMod, Q, exec, $terminal bind = $mainMod, C, killactive, bind = $mainMod, M, exit, -bind = $mainMod, E, exec, dolphin +bind = $mainMod, E, exec, $fileManager bind = $mainMod, V, togglefloating, -bind = $mainMod, R, exec, wofi --show drun +bind = $mainMod, R, exec, $menu bind = $mainMod, P, pseudo, # dwindle bind = $mainMod, J, togglesplit, # dwindle From c6804ccaab1cdd0de5026907e3537ad5362861a9 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Dec 2023 00:42:58 +0000 Subject: [PATCH 332/513] opengl: fixup blur dirty repaint conditions with solitary fixes #4025 --- src/render/OpenGL.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 2c9151e5..fde04c5f 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1207,13 +1207,6 @@ CFramebuffer* CHyprOpenGLImpl::blurMainFramebufferWithDamage(float a, CRegion* o } void CHyprOpenGLImpl::markBlurDirtyForMonitor(CMonitor* pMonitor) { - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pMonitor->activeWorkspace); - const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(pMonitor->activeWorkspace); - - if (PWORKSPACE->m_bHasFullscreenWindow && PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL && PFULLWINDOW && !PFULLWINDOW->m_vRealSize.isBeingAnimated() && - PFULLWINDOW->opaque()) - return; - m_mMonitorRenderResources[pMonitor].blurFBDirty = true; } @@ -1225,6 +1218,10 @@ void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) { if (!*PBLURNEWOPTIMIZE || !m_mMonitorRenderResources[pMonitor].blurFBDirty || !*PBLUR) return; + // ignore if solitary present, nothing to blur + if (pMonitor->solitaryClient) + return; + // check if we need to update the blur fb // if there are no windows that would benefit from it, // we will ignore that the blur FB is dirty. From 2d04cb1cc664b8f16a42cae6e4c5dd5848712bf5 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Dec 2023 00:48:39 +0000 Subject: [PATCH 333/513] input: make fallback layout us --- src/managers/input/InputManager.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 77eabeb7..25f0e34c 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -593,10 +593,10 @@ void CInputManager::setClickMode(eClickBehaviorMode mode) { void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { // notify the keybind manager - static auto* const PPASSMOUSE = &g_pConfigManager->getConfigValuePtr("binds:pass_mouse_when_bound")->intValue; - const auto PASS = g_pKeybindManager->onMouseEvent(e); - static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; - static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue; + static auto* const PPASSMOUSE = &g_pConfigManager->getConfigValuePtr("binds:pass_mouse_when_bound")->intValue; + const auto PASS = g_pKeybindManager->onMouseEvent(e); + static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; + static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue; static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; static auto* const PBORDERGRABEXTEND = &g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area")->intValue; const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0; @@ -899,7 +899,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) { pKeyboard->currentRules.model = ""; pKeyboard->currentRules.variant = ""; pKeyboard->currentRules.options = ""; - pKeyboard->currentRules.layout = ""; + pKeyboard->currentRules.layout = "us"; KEYMAP = xkb_keymap_new_from_names(CONTEXT, &rules, XKB_KEYMAP_COMPILE_NO_FLAGS); } From 3bb9c7c5cf4f2ee30bf821501499f2308d616f94 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Dec 2023 00:52:16 +0000 Subject: [PATCH 334/513] props: bump ver to 0.33.0 --- props.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/props.json b/props.json index 3068f9ca..6634dabf 100644 --- a/props.json +++ b/props.json @@ -1,3 +1,3 @@ { - "version": "0.32.3" + "version": "0.33.0" } \ No newline at end of file From 83248b6936c00ddef6a39fa31a37949ca1a34ffe Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Dec 2023 14:43:54 +0000 Subject: [PATCH 335/513] toplevelexport: fix getPreferredReadFormat param in captureToplevel fixes #4043 --- src/protocols/ToplevelExport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index dabad2ab..23ae996e 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -178,7 +178,7 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou const auto PMONITOR = g_pCompositor->getMonitorFromID(PFRAME->pWindow->m_iMonitorID); g_pHyprRenderer->makeEGLCurrent(); - PFRAME->shmFormat = g_pHyprOpenGL->getPreferredReadFormat(PFRAME->pMonitor); + PFRAME->shmFormat = g_pHyprOpenGL->getPreferredReadFormat(PMONITOR); if (PFRAME->shmFormat == DRM_FORMAT_INVALID) { Debug::log(ERR, "No format supported by renderer in capture toplevel"); hyprland_toplevel_export_frame_v1_send_failed(resource); From da863459c49c8b9a82e6a1180c2592a2b63feccd Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Dec 2023 14:59:12 +0000 Subject: [PATCH 336/513] screencopy: fix legacyrenderer builds fixes #4044 --- src/protocols/Screencopy.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index e5aaab62..8537a701 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -455,7 +455,11 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* g_pHyprOpenGL->renderTexture(sourceTex, &monbox, 1); g_pHyprOpenGL->setMonitorTransformEnabled(true); +#ifndef GLES2 glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.m_iFb); +#else + glBindFramebuffer(GL_FRAMEBUFFER, fb.m_iFb); +#endif const auto PFORMAT = g_pHyprOpenGL->getPixelFormatFromDRM(format); if (!PFORMAT) { From 37d7a8c64dfabfe81330c819c24fd6b13b292194 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Dec 2023 15:41:17 +0000 Subject: [PATCH 337/513] framebuffer: ignore addStencil on legacyRenderer ref #4044 --- src/render/Framebuffer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/render/Framebuffer.cpp b/src/render/Framebuffer.cpp index eed23699..d35e5119 100644 --- a/src/render/Framebuffer.cpp +++ b/src/render/Framebuffer.cpp @@ -57,6 +57,8 @@ bool CFramebuffer::alloc(int w, int h, uint32_t drmFormat) { } void CFramebuffer::addStencil() { + // TODO: Allow this with gles2 +#ifndef GLES2 glBindTexture(GL_TEXTURE_2D, m_pStencilTex->m_iTexID); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, m_vSize.x, m_vSize.y, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0); @@ -69,6 +71,7 @@ void CFramebuffer::addStencil() { glBindTexture(GL_TEXTURE_2D, 0); glBindFramebuffer(GL_FRAMEBUFFER, g_pHyprOpenGL->m_iCurrentOutputFb); +#endif } void CFramebuffer::bind() { From ab66fa430efd1e8b9b6a0220b896998215fff8c3 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 5 Dec 2023 20:04:53 +0000 Subject: [PATCH 338/513] screencopy: fix glReadPixels offset fixes #4042 --- src/protocols/Screencopy.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 8537a701..18fe09f4 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -481,11 +481,11 @@ bool CScreencopyProtocolManager::copyFrameShm(SScreencopyFrame* frame, timespec* uint32_t packStride = pixel_format_info_min_stride(drmFmtWlr, frame->box.w); if (packStride == stride) { - glReadPixels(frame->box.x, frame->box.y, frame->box.w, frame->box.h, PFORMAT->glFormat, PFORMAT->glType, data); + glReadPixels(0, 0, frame->box.w, frame->box.h, PFORMAT->glFormat, PFORMAT->glType, data); } else { for (size_t i = 0; i < frame->box.h; ++i) { - uint32_t y = frame->box.x + i; - glReadPixels(frame->box.x, y, frame->box.w, 1, PFORMAT->glFormat, PFORMAT->glType, ((unsigned char*)data) + i * stride); + uint32_t y = i; + glReadPixels(0, y, frame->box.w, 1, PFORMAT->glFormat, PFORMAT->glType, ((unsigned char*)data) + i * stride); } } From cfd94c5b30719c1c512b0d0ef4366a0cb64793e0 Mon Sep 17 00:00:00 2001 From: dranull <150595692+dranull@users.noreply.github.com> Date: Tue, 5 Dec 2023 21:16:26 +0000 Subject: [PATCH 339/513] input: Stop propagating axis events after valid binds (#4059) --- src/managers/input/InputManager.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 25f0e34c..b3aadeed 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -699,6 +699,9 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) { g_pCompositor->notifyIdleActivity(); + if (!passEvent) + return; + const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); const auto pWindow = g_pCompositor->vectorToWindowIdeal(MOUSECOORDS); @@ -713,8 +716,7 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) { } } - if (passEvent) - wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, factor * e->delta, std::round(factor * e->delta_discrete), e->source); + wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, factor * e->delta, std::round(factor * e->delta_discrete), e->source); } Vector2D CInputManager::getMouseCoordsInternal() { From 8bd86cf37e245088433156796f1bc72542ca09ad Mon Sep 17 00:00:00 2001 From: Tungsten842 Date: Wed, 6 Dec 2023 00:39:57 +0100 Subject: [PATCH 340/513] hyprctl: order commands alphabetically (#4061) --- hyprctl/main.cpp | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 74127d5b..a53c4c3f 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -26,33 +26,33 @@ const std::string USAGE = R"#(usage: hyprctl [(opt)flags] [command] [(opt)args] commands: - monitors - workspaces - activeworkspace - workspacerules - clients activewindow - layers - devices + activeworkspace binds + clients + cursorpos + devices dispatch - keyword - version - kill - splash + getoption + globalshortcuts hyprpaper + instances + keyword + kill + layers + layouts + monitors + notify + plugin reload setcursor - getoption - cursorpos - switchxkblayout seterror setprop - plugin - notify - globalshortcuts - instances - layouts + splash + switchxkblayout + version + workspacerules + workspaces flags: -j -> output in JSON From 13b4c6de869b782ae18a0e8ac7c590e8000cc1c2 Mon Sep 17 00:00:00 2001 From: swwind Date: Wed, 6 Dec 2023 22:30:40 +0800 Subject: [PATCH 341/513] input: don't send mouse events on touch (#4071) --- src/managers/input/Touch.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/managers/input/Touch.cpp b/src/managers/input/Touch.cpp index 965eee86..600df302 100644 --- a/src/managers/input/Touch.cpp +++ b/src/managers/input/Touch.cpp @@ -72,7 +72,7 @@ void CInputManager::onTouchMove(wlr_touch_motion_event* e) { local = local * m_sTouchData.touchFocusWindow->m_fX11SurfaceScaledBy; wlr_seat_touch_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id, local.x, local.y); - wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, local.x, local.y); + // wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, local.x, local.y); } else if (m_sTouchData.touchFocusLS) { const auto PMONITOR = g_pCompositor->getMonitorFromID(m_sTouchData.touchFocusLS->monitorID); @@ -81,7 +81,7 @@ void CInputManager::onTouchMove(wlr_touch_motion_event* e) { const auto local = g_pInputManager->getMouseCoordsInternal() - m_sTouchData.touchSurfaceOrigin; wlr_seat_touch_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, e->touch_id, local.x, local.y); - wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, local.x, local.y); + // wlr_seat_pointer_notify_motion(g_pCompositor->m_sSeat.seat, e->time_msec, local.x, local.y); } } From 03c6f4506ab06d2920c59b3c64f45cb4eec8c97a Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 6 Dec 2023 14:46:18 +0000 Subject: [PATCH 342/513] internal: various improvements to avoid crashes on exit --- src/Compositor.cpp | 3 ++- src/Window.cpp | 3 +++ src/debug/Log.hpp | 4 ++++ src/helpers/WLClasses.cpp | 3 +++ src/render/Renderbuffer.cpp | 3 +++ src/render/Renderer.cpp | 3 +++ 6 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 9419583e..98f51204 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -339,7 +339,8 @@ void CCompositor::cleanup() { removeLockFile(); - m_bIsShuttingDown = true; + m_bIsShuttingDown = true; + Debug::shuttingDown = true; #ifdef USES_SYSTEMD if (sd_booted() > 0) diff --git a/src/Window.cpp b/src/Window.cpp index bcb819a8..789882de 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -22,6 +22,9 @@ CWindow::~CWindow() { g_pCompositor->m_pLastWindow = nullptr; } + if (!g_pHyprOpenGL) + return; + g_pHyprRenderer->makeEGLCurrent(); std::erase_if(g_pHyprOpenGL->m_mWindowFramebuffers, [&](const auto& other) { return other.first == this; }); } diff --git a/src/debug/Log.hpp b/src/debug/Log.hpp index 659e2db4..d9a7f6aa 100644 --- a/src/debug/Log.hpp +++ b/src/debug/Log.hpp @@ -27,6 +27,7 @@ namespace Debug { inline int64_t* disableTime = nullptr; inline bool disableStdout = false; inline bool trace = false; + inline bool shuttingDown = false; inline std::string rollingLog = ""; // rolling log contains the ROLLING_LOG_SIZE tail of the log @@ -36,6 +37,9 @@ namespace Debug { if (level == TRACE && !trace) return; + if (shuttingDown) + return; + std::string logMsg = ""; switch (level) { diff --git a/src/helpers/WLClasses.cpp b/src/helpers/WLClasses.cpp index 9a326614..960145b9 100644 --- a/src/helpers/WLClasses.cpp +++ b/src/helpers/WLClasses.cpp @@ -9,6 +9,9 @@ SLayerSurface::SLayerSurface() { } SLayerSurface::~SLayerSurface() { + if (!g_pHyprOpenGL) + return; + g_pHyprRenderer->makeEGLCurrent(); std::erase_if(g_pHyprOpenGL->m_mLayerFramebuffers, [&](const auto& other) { return other.first == this; }); } diff --git a/src/render/Renderbuffer.cpp b/src/render/Renderbuffer.cpp index 0643904b..9434c3f0 100644 --- a/src/render/Renderbuffer.cpp +++ b/src/render/Renderbuffer.cpp @@ -5,6 +5,9 @@ #include CRenderbuffer::~CRenderbuffer() { + if (!g_pCompositor) + return; + if (eglGetCurrentContext() != wlr_egl_get_context(g_pCompositor->m_sWLREGL)) eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index b7b6ae96..8206dc2b 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2281,6 +2281,9 @@ CRenderbuffer* CHyprRenderer::getOrCreateRenderbuffer(wlr_buffer* buffer, uint32 } void CHyprRenderer::makeEGLCurrent() { + if (!g_pCompositor) + return; + if (eglGetCurrentContext() != wlr_egl_get_context(g_pCompositor->m_sWLREGL)) eglMakeCurrent(wlr_egl_get_display(g_pCompositor->m_sWLREGL), EGL_NO_SURFACE, EGL_NO_SURFACE, wlr_egl_get_context(g_pCompositor->m_sWLREGL)); } From c4bd91ec8ab9cad3f14fbbdc84ba5601aaca1a95 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 6 Dec 2023 15:31:23 +0000 Subject: [PATCH 343/513] makefile: only require version.h before installheaders --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0c0b9d10..6213102e 100644 --- a/Makefile +++ b/Makefile @@ -68,7 +68,7 @@ pluginenv: @exit 1 installheaders: - @if [ ! -f ./build/Hyprland ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi + @if [ ! -f ./src/version.h ]; then echo -en "You need to run $(MAKE) all first.\n" && exit 1; fi mkdir -p ${PREFIX}/include/hyprland mkdir -p ${PREFIX}/include/hyprland/protocols From d74607e414dcd16911089a6d4b6aeb661c880923 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 6 Dec 2023 16:47:26 +0000 Subject: [PATCH 344/513] props: bump ver to 0.33.1 --- props.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/props.json b/props.json index 6634dabf..36248fd8 100644 --- a/props.json +++ b/props.json @@ -1,3 +1,3 @@ { - "version": "0.33.0" + "version": "0.33.1" } \ No newline at end of file From 5489f9f07a73c6b5b97702731a5092463a01fb5b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 6 Dec 2023 20:17:40 +0000 Subject: [PATCH 345/513] renderer: use xray for background blur on small() surfaces ref #4050 --- src/render/OpenGL.cpp | 7 +++++-- src/render/OpenGL.hpp | 5 ++--- src/render/Renderer.cpp | 3 ++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index fde04c5f..845b3caa 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -583,14 +583,14 @@ void CHyprOpenGLImpl::renderRect(CBox* box, const CColor& col, int round) { renderRectWithDamage(box, col, &m_RenderData.damage, round); } -void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round, float blurA) { +void CHyprOpenGLImpl::renderRectWithBlur(CBox* box, const CColor& col, int round, float blurA, bool xray) { if (m_RenderData.damage.empty()) return; CRegion damage{m_RenderData.damage}; damage.intersect(*box); - CFramebuffer* POUTFB = blurMainFramebufferWithDamage(blurA, &damage); + CFramebuffer* POUTFB = xray ? &m_RenderData.pCurrentMonData->blurFB : blurMainFramebufferWithDamage(blurA, &damage); m_RenderData.currentFB->bind(); @@ -1233,6 +1233,9 @@ void CHyprOpenGLImpl::preRender(CMonitor* pMonitor) { if (pWindow->m_sAdditionalConfigData.forceNoBlur) return false; + if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall) + return true; + const auto PSURFACE = pWindow->m_pWLSurface.wlr(); const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index efccaad4..01e05af1 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -120,7 +120,7 @@ class CHyprOpenGLImpl { void end(); void renderRect(CBox*, const CColor&, int round = 0); - void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f); + void renderRectWithBlur(CBox*, const CColor&, int round = 0, float blurA = 1.f, bool xray = false); void renderRectWithDamage(CBox*, const CColor&, CRegion* damage, int round = 0); void renderTexture(wlr_texture*, CBox*, float a, int round = 0, bool allowCustomUV = false); void renderTexture(const CTexture&, CBox*, float a, int round = 0, bool discardActive = false, bool allowCustomUV = false); @@ -142,6 +142,7 @@ class CHyprOpenGLImpl { void makeLayerSnapshot(SLayerSurface*); void renderSnapshot(CWindow**); void renderSnapshot(SLayerSurface**); + bool shouldUseNewBlurOptimizations(SLayerSurface* pLayer, CWindow* pWindow); void clear(const CColor&); void clearWithTex(); @@ -223,8 +224,6 @@ class CHyprOpenGLImpl { void preBlurForCurrentMonitor(); - bool shouldUseNewBlurOptimizations(SLayerSurface* pLayer, CWindow* pWindow); - bool passRequiresIntrospection(CMonitor* pMonitor); friend class CHyprRenderer; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 8206dc2b..d20e10b8 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -502,7 +502,8 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* if (pWindow->m_pWLSurface.small() && !pWindow->m_pWLSurface.m_bFillIgnoreSmall && renderdata.blur && *PBLUR) { CBox wb = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h}; wb.scale(pMonitor->scale).round(); - g_pHyprOpenGL->renderRectWithBlur(&wb, CColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1, renderdata.fadeAlpha); + g_pHyprOpenGL->renderRectWithBlur(&wb, CColor(0, 0, 0, 0), renderdata.dontRound ? 0 : renderdata.rounding - 1, renderdata.fadeAlpha, + g_pHyprOpenGL->shouldUseNewBlurOptimizations(nullptr, pWindow)); renderdata.blur = false; } From 4a42344e9748d2b44c55798ddc3fa41448533c4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Conzelmann?= <45296195+zephvr@users.noreply.github.com> Date: Wed, 6 Dec 2023 23:54:56 +0100 Subject: [PATCH 346/513] style/ci: apply clang-format and verify it in ci (#4039) * style: apply clang-format * ci: add new clang-format job to CI --- .clang-format-ignore | 1 + .github/workflows/ci.yaml | 29 +++++++++++ src/Compositor.hpp | 3 +- src/SharedDefs.hpp | 6 +-- src/Window.hpp | 6 +-- src/debug/CrashReporter.cpp | 26 +++++----- src/debug/HyprCtl.cpp | 29 +++++------ src/debug/HyprCtl.hpp | 3 +- src/debug/HyprNotificationOverlay.hpp | 7 ++- src/debug/Log.hpp | 3 +- src/events/Popups.cpp | 2 +- src/helpers/AnimatedVariable.hpp | 12 ++--- src/helpers/Monitor.hpp | 2 +- src/helpers/WLSurface.hpp | 6 +-- src/helpers/Workspace.cpp | 4 +- src/helpers/XWaylandStubs.hpp | 3 +- src/includes.hpp | 2 +- src/init/initHelpers.cpp | 4 +- src/layout/IHyprLayout.hpp | 6 +-- src/macros.hpp | 10 ++-- src/managers/EventManager.hpp | 1 + src/managers/KeybindManager.hpp | 3 +- src/managers/input/InputManager.cpp | 2 +- src/managers/input/InputManager.hpp | 9 ++-- src/managers/input/Swipe.cpp | 52 +++++++------------ src/plugins/HookSystem.hpp | 6 +-- src/protocols/FractionalScale.cpp | 4 +- src/protocols/Screencopy.hpp | 3 +- src/render/OpenGL.hpp | 3 +- src/render/Renderer.hpp | 9 ++-- src/render/Texture.hpp | 3 +- .../decorations/DecorationPositioner.hpp | 6 +-- .../decorations/IHyprWindowDecoration.hpp | 9 ++-- 33 files changed, 131 insertions(+), 143 deletions(-) create mode 100644 .clang-format-ignore diff --git a/.clang-format-ignore b/.clang-format-ignore new file mode 100644 index 00000000..c6bf34ed --- /dev/null +++ b/.clang-format-ignore @@ -0,0 +1 @@ +subprojects/**/* diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a78b7522..54248e3a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -106,3 +106,32 @@ jobs: run: mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DNO_XWAYLAND:STRING=true -H./ -B./build -G Ninja - name: Compile run: make release + + clang-format: + name: "Code Style (Arch)" + runs-on: ubuntu-latest + container: + image: archlinux + steps: + - name: Download dependencies + run: | + sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf + pacman --noconfirm --noprogressbar -Syyu + pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd cmake jq python libliftoff tomlplusplus + - name: Set up user + run: | + useradd -m githubuser + echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers + - name: Install libdisplay-info from the AUR + run: | + su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar" + - name: Checkout Hyprland + uses: actions/checkout@v3 + with: + submodules: true + - name: Configure + run: | + meson obj-x86_64-pc-linux-gnu \ + -Ddefault_library=static + - name: clang-format check + run: ninja -C obj-x86_64-pc-linux-gnu clang-format-check diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 8ca43d84..65550154 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -29,8 +29,7 @@ #include "plugins/PluginSystem.hpp" #include "helpers/Watchdog.hpp" -enum eManagersInitStage -{ +enum eManagersInitStage { STAGE_PRIORITY = 0, STAGE_LATE }; diff --git a/src/SharedDefs.hpp b/src/SharedDefs.hpp index 19d26b61..4b1524b3 100644 --- a/src/SharedDefs.hpp +++ b/src/SharedDefs.hpp @@ -2,8 +2,7 @@ #include "helpers/Vector2D.hpp" -enum eIcons -{ +enum eIcons { ICON_WARNING = 0, ICON_INFO, ICON_HINT, @@ -13,8 +12,7 @@ enum eIcons ICON_NONE }; -enum eRenderStage -{ +enum eRenderStage { RENDER_PRE = 0, /* Before binding the gl context */ RENDER_BEGIN, /* Just when the rendering begins, nothing has been rendered yet. Damage, current render data in opengl valid. */ RENDER_PRE_WINDOWS, /* Pre windows, post bottom and overlay layers */ diff --git a/src/Window.hpp b/src/Window.hpp index 4e1ab9c1..f9873ead 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -11,16 +11,14 @@ #include "macros.hpp" #include "managers/XWaylandManager.hpp" -enum eIdleInhibitMode -{ +enum eIdleInhibitMode { IDLEINHIBIT_NONE = 0, IDLEINHIBIT_ALWAYS, IDLEINHIBIT_FULLSCREEN, IDLEINHIBIT_FOCUS }; -enum eGroupRules -{ +enum eGroupRules { // effective only during first map, except for _ALWAYS variant GROUP_NONE = 0, GROUP_SET = 1 << 0, // Open as new group or add to focused group diff --git a/src/debug/CrashReporter.cpp b/src/debug/CrashReporter.cpp index 14aa5c5b..dac96fb3 100644 --- a/src/debug/CrashReporter.cpp +++ b/src/debug/CrashReporter.cpp @@ -13,19 +13,19 @@ std::string getRandomMessage() { const std::vector MESSAGES = {"Sorry, didn't mean to...", - "This was an accident, I swear!", - "Calm down, it was a misinput! MISINPUT!", - "Oops", - "Vaxry is going to be upset.", - "Who tried dividing by zero?!", - "Maybe you should try dusting your PC in the meantime?", - "I tried so hard, and got so far...", - "I don't feel so good...", - "*thud*", - "Well this is awkward.", - "\"stable\"", - "I hope you didn't have any unsaved progress.", - "All these computers..."}; + "This was an accident, I swear!", + "Calm down, it was a misinput! MISINPUT!", + "Oops", + "Vaxry is going to be upset.", + "Who tried dividing by zero?!", + "Maybe you should try dusting your PC in the meantime?", + "I tried so hard, and got so far...", + "I don't feel so good...", + "*thud*", + "Well this is awkward.", + "\"stable\"", + "I hope you didn't have any unsaved progress.", + "All these computers..."}; std::random_device dev; std::mt19937 engine(dev()); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 91bbe264..98526ef4 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -75,10 +75,9 @@ std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat f "vrr": {}, "activelyTearing": {} }},)#", - m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->szDescription), (m->output->make ? m->output->make : ""), - (m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, - (int)m->vecPosition.x, (int)m->vecPosition.y, m->activeWorkspace, - (m->activeWorkspace == -1 ? "" : escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName)), m->specialWorkspaceID, + m->ID, escapeJSONStrings(m->szName), escapeJSONStrings(m->szDescription), (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), + (m->output->serial ? m->output->serial : ""), (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, + m->activeWorkspace, (m->activeWorkspace == -1 ? "" : escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName)), m->specialWorkspaceID, escapeJSONStrings(getWorkspaceNameFromSpecialID(m->specialWorkspaceID)), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "true" : "false"), (m->dpmsStatus ? "true" : "false"), (m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED ? "true" : "false"), @@ -93,17 +92,17 @@ std::string monitorsRequest(std::string request, HyprCtl::eHyprCtlOutputFormat f if (!m->output || m->ID == -1ull) continue; - result += std::format( - "Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\tspecial " - "workspace: {} ({})\n\treserved: {} " - "{} {} {}\n\tscale: {:.2f}\n\ttransform: " - "{}\n\tfocused: {}\n\tdpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\n", - m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, - m->szDescription, (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), - (m->output->serial ? m->output->serial : ""), m->activeWorkspace, (m->activeWorkspace == -1 ? "" : g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName), - m->specialWorkspaceID, getWorkspaceNameFromSpecialID(m->specialWorkspaceID), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, - (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"), - (int)m->dpmsStatus, (int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED), m->tearingState.activelyTearing); + result += + std::format("Monitor {} (ID {}):\n\t{}x{}@{:.5f} at {}x{}\n\tdescription: {}\n\tmake: {}\n\tmodel: {}\n\tserial: {}\n\tactive workspace: {} ({})\n\tspecial " + "workspace: {} ({})\n\treserved: {} " + "{} {} {}\n\tscale: {:.2f}\n\ttransform: " + "{}\n\tfocused: {}\n\tdpmsStatus: {}\n\tvrr: {}\n\tactivelyTearing: {}\n\n", + m->szName, m->ID, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y, m->refreshRate, (int)m->vecPosition.x, (int)m->vecPosition.y, m->szDescription, + (m->output->make ? m->output->make : ""), (m->output->model ? m->output->model : ""), (m->output->serial ? m->output->serial : ""), m->activeWorkspace, + (m->activeWorkspace == -1 ? "" : g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName), m->specialWorkspaceID, + getWorkspaceNameFromSpecialID(m->specialWorkspaceID), (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, + (int)m->vecReservedBottomRight.y, m->scale, (int)m->transform, (m.get() == g_pCompositor->m_pLastMonitor ? "yes" : "no"), (int)m->dpmsStatus, + (int)(m->output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED), m->tearingState.activelyTearing); } } diff --git a/src/debug/HyprCtl.hpp b/src/debug/HyprCtl.hpp index 4816c63c..00cf7c5b 100644 --- a/src/debug/HyprCtl.hpp +++ b/src/debug/HyprCtl.hpp @@ -19,8 +19,7 @@ namespace HyprCtl { inline int iSocketFD = -1; - enum eHyprCtlOutputFormat - { + enum eHyprCtlOutputFormat { FORMAT_NORMAL = 0, FORMAT_JSON }; diff --git a/src/debug/HyprNotificationOverlay.hpp b/src/debug/HyprNotificationOverlay.hpp index 46a9a3d0..84e61f80 100644 --- a/src/debug/HyprNotificationOverlay.hpp +++ b/src/debug/HyprNotificationOverlay.hpp @@ -10,16 +10,15 @@ #include -enum eIconBackend -{ +enum eIconBackend { ICONS_BACKEND_NONE = 0, ICONS_BACKEND_NF, ICONS_BACKEND_FA }; static const std::array, 3 /* backends */> ICONS_ARRAY = { - std::array{"[!]", "[i]", "[Hint]", "[Err]", "[?]", "[ok]", ""}, std::array{"", "", "", "", "", "󰸞", ""}, - std::array{"", "", "", "", "", ""}}; + std::array{"[!]", "[i]", "[Hint]", "[Err]", "[?]", "[ok]", ""}, + std::array{"", "", "", "", "", "󰸞", ""}, std::array{"", "", "", "", "", ""}}; static const std::array ICONS_COLORS = {CColor{255.0 / 255.0, 204 / 255.0, 102 / 255.0, 1.0}, CColor{128 / 255.0, 255 / 255.0, 255 / 255.0, 1.0}, CColor{179 / 255.0, 255 / 255.0, 204 / 255.0, 1.0}, diff --git a/src/debug/Log.hpp b/src/debug/Log.hpp index d9a7f6aa..3d2ed48c 100644 --- a/src/debug/Log.hpp +++ b/src/debug/Log.hpp @@ -10,8 +10,7 @@ #define LOGMESSAGESIZE 1024 #define ROLLING_LOG_SIZE 4096 -enum LogLevel -{ +enum LogLevel { NONE = -1, LOG = 0, WARN, diff --git a/src/events/Popups.cpp b/src/events/Popups.cpp index c8898c3b..bcdb1808 100644 --- a/src/events/Popups.cpp +++ b/src/events/Popups.cpp @@ -191,7 +191,7 @@ void Events::listener_repositionPopupXDG(void* owner, void* data) { const auto PMONITOR = g_pCompositor->m_pLastMonitor; CBox box = {PMONITOR->vecPosition.x - lx + PPOPUP->popup->current.geometry.x, PMONITOR->vecPosition.y - ly + PPOPUP->popup->current.geometry.y, PMONITOR->vecSize.x, - PMONITOR->vecSize.y}; + PMONITOR->vecSize.y}; wlr_xdg_popup_unconstrain_from_box(PPOPUP->popup, box.pWlr()); } diff --git a/src/helpers/AnimatedVariable.hpp b/src/helpers/AnimatedVariable.hpp index 059e892d..d87273b3 100644 --- a/src/helpers/AnimatedVariable.hpp +++ b/src/helpers/AnimatedVariable.hpp @@ -8,16 +8,14 @@ #include "../macros.hpp" #include "../debug/Log.hpp" -enum ANIMATEDVARTYPE -{ +enum ANIMATEDVARTYPE { AVARTYPE_INVALID = -1, AVARTYPE_FLOAT, AVARTYPE_VECTOR, AVARTYPE_COLOR }; -enum AVARDAMAGEPOLICY -{ +enum AVARDAMAGEPOLICY { AVARDAMAGE_NONE = -1, AVARDAMAGE_ENTIRE = 0, AVARDAMAGE_BORDER, @@ -37,10 +35,10 @@ class CAnimatedVariable { void create(ANIMATEDVARTYPE, SAnimationPropertyConfig*, void* pWindow, AVARDAMAGEPOLICY); void create(ANIMATEDVARTYPE, std::any val, SAnimationPropertyConfig*, void* pWindow, AVARDAMAGEPOLICY); - CAnimatedVariable(const CAnimatedVariable&) = delete; - CAnimatedVariable(CAnimatedVariable&&) = delete; + CAnimatedVariable(const CAnimatedVariable&) = delete; + CAnimatedVariable(CAnimatedVariable&&) = delete; CAnimatedVariable& operator=(const CAnimatedVariable&) = delete; - CAnimatedVariable& operator=(CAnimatedVariable&&) = delete; + CAnimatedVariable& operator=(CAnimatedVariable&&) = delete; ~CAnimatedVariable(); diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 7621ac17..f44e2c16 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -42,7 +42,7 @@ class CMonitor { int activeWorkspace = -1; float scale = 1; - std::string szName = ""; + std::string szName = ""; std::string szDescription = ""; Vector2D vecReservedTopLeft = Vector2D(0, 0); diff --git a/src/helpers/WLSurface.hpp b/src/helpers/WLSurface.hpp index 8b4ef835..faef4353 100644 --- a/src/helpers/WLSurface.hpp +++ b/src/helpers/WLSurface.hpp @@ -13,10 +13,10 @@ class CWLSurface { void assign(wlr_surface* pSurface); void unassign(); - CWLSurface(const CWLSurface&) = delete; - CWLSurface(CWLSurface&&) = delete; + CWLSurface(const CWLSurface&) = delete; + CWLSurface(CWLSurface&&) = delete; CWLSurface& operator=(const CWLSurface&) = delete; - CWLSurface& operator=(CWLSurface&&) = delete; + CWLSurface& operator=(CWLSurface&&) = delete; wlr_surface* wlr() const; bool exists() const; diff --git a/src/helpers/Workspace.cpp b/src/helpers/Workspace.cpp index c027688e..213607d0 100644 --- a/src/helpers/Workspace.cpp +++ b/src/helpers/Workspace.cpp @@ -90,7 +90,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { } } else if (ANIMSTYLE == "slidevert") { // fallback is slide - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + 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. @@ -103,7 +103,7 @@ void CWorkspace::startAnim(bool in, bool left, bool instant) { } } else { // fallback is slide - const auto PMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); + 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. diff --git a/src/helpers/XWaylandStubs.hpp b/src/helpers/XWaylandStubs.hpp index 904867cf..89e0b41f 100644 --- a/src/helpers/XWaylandStubs.hpp +++ b/src/helpers/XWaylandStubs.hpp @@ -28,8 +28,7 @@ typedef struct { } xcb_size_hints_t; typedef unsigned int xcb_window_t; -typedef enum xcb_stack_mode_t -{ +typedef enum xcb_stack_mode_t { XCB_STACK_MODE_ABOVE = 0, XCB_STACK_MODE_BELOW = 1, XCB_STACK_MODE_TOP_IF = 2, diff --git a/src/includes.hpp b/src/includes.hpp index 611e4a5c..961729ad 100644 --- a/src/includes.hpp +++ b/src/includes.hpp @@ -27,7 +27,7 @@ // pthread first because it uses class in a C++ way and XWayland includes that... #include -#define class _class +#define class _class #define namespace _namespace #define static #define delete delete_ diff --git a/src/init/initHelpers.cpp b/src/init/initHelpers.cpp index 2a296d2e..2cc491d0 100644 --- a/src/init/initHelpers.cpp +++ b/src/init/initHelpers.cpp @@ -5,8 +5,8 @@ bool Init::isSudo() { } void Init::gainRealTime() { - const int minPrio = sched_get_priority_min(SCHED_RR); - int old_policy; + const int minPrio = sched_get_priority_min(SCHED_RR); + int old_policy; struct sched_param param; if (pthread_getschedparam(pthread_self(), &old_policy, ¶m)) { diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index 32f95a22..5c74078e 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -15,8 +15,7 @@ struct SLayoutMessageHeader { enum eFullscreenMode : int8_t; -enum eRectCorner -{ +enum eRectCorner { CORNER_NONE = 0, CORNER_TOPLEFT, CORNER_TOPRIGHT, @@ -24,8 +23,7 @@ enum eRectCorner CORNER_BOTTOMLEFT }; -enum eDirection -{ +enum eDirection { DIRECTION_DEFAULT = -1, DIRECTION_UP = 0, DIRECTION_RIGHT, diff --git a/src/macros.hpp b/src/macros.hpp index c2eb98db..19b4cbc6 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -44,7 +44,7 @@ if (!(expr)) { \ Debug::log(CRIT, "\n==========================================================================================\nASSERTION FAILED! \n\n{}\n\nat: line {} in {}", \ std::format(reason, ##__VA_ARGS__), __LINE__, \ - ([]() constexpr->std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })()); \ + ([]() constexpr -> std::string { return std::string(__FILE__).substr(std::string(__FILE__).find_last_of('/') + 1); })()); \ printf("Assertion failed! See the log in /tmp/hypr/hyprland.log for more info."); \ raise(SIGABRT); \ } @@ -63,9 +63,7 @@ } #define FORMAT_FLAG(spec__, flag__) \ - case spec__: \ - (flag__) = true; \ - break; + case spec__: (flag__) = true; break; #define FORMAT_NUMBER(buf__) \ case '0': \ @@ -77,9 +75,7 @@ case '6': \ case '7': \ case '8': \ - case '9': \ - (buf__).push_back(*it); \ - break; + case '9': (buf__).push_back(*it); break; #if ISDEBUG #define UNREACHABLE() \ diff --git a/src/managers/EventManager.hpp b/src/managers/EventManager.hpp index be2bf2d5..68cda1ee 100644 --- a/src/managers/EventManager.hpp +++ b/src/managers/EventManager.hpp @@ -20,6 +20,7 @@ class CEventManager { void startThread(); std::thread m_tThread; + private: void flushEvents(); diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 8a0b3b89..73997dd6 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -29,8 +29,7 @@ struct SKeybind { bool shadowed = false; }; -enum eFocusWindowMode -{ +enum eFocusWindowMode { MODE_CLASS_REGEX = 0, MODE_TITLE_REGEX, MODE_ADDRESS, diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index b3aadeed..9ef1b4a3 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1657,7 +1657,7 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) { CBox box = w->getWindowMainSurfaceBox(); eBorderIconDirection direction = BORDERICON_NONE; CBox boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE), - box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; + box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; if (w->hasPopupAt(mouseCoords)) direction = BORDERICON_NONE; diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index b6d9d89c..5fa5824e 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -7,14 +7,12 @@ #include "../../helpers/Timer.hpp" #include "InputMethodRelay.hpp" -enum eClickBehaviorMode -{ +enum eClickBehaviorMode { CLICKMODE_DEFAULT = 0, CLICKMODE_KILL }; -enum eMouseBindMode -{ +enum eMouseBindMode { MBIND_INVALID = -1, MBIND_MOVE = 0, MBIND_RESIZE = 1, @@ -22,8 +20,7 @@ enum eMouseBindMode MBIND_RESIZE_FORCE_RATIO = 3 }; -enum eBorderIconDirection -{ +enum eBorderIconDirection { BORDERICON_NONE, BORDERICON_UP, BORDERICON_DOWN, diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index d093b8c3..f345e4f5 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -76,12 +76,12 @@ void CInputManager::onSwipeEnd(wlr_pointer_swipe_end_event* e) { workspaceIDRight = maxWorkspace + 1; } - auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); // not guaranteed if PSWIPENEW || PSWIPENUMBER - auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); // not guaranteed if PSWIPENUMBER + auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); // not guaranteed if PSWIPENEW || PSWIPENUMBER + auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); // not guaranteed if PSWIPENUMBER - const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.vec(); - const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + *PWORKSPACEGAP; - const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + *PWORKSPACEGAP; + const auto RENDEROFFSETMIDDLE = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.vec(); + const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + *PWORKSPACEGAP; + const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + *PWORKSPACEGAP; CWorkspace* pSwitchedTo = nullptr; @@ -204,9 +204,9 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { static auto* const PSWIPEUSER = &g_pConfigManager->getConfigValuePtr("gestures:workspace_swipe_use_r")->intValue; static auto* const PWORKSPACEGAP = &g_pConfigManager->getConfigValuePtr("general:gaps_workspaces")->intValue; - const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + *PWORKSPACEGAP; - const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + *PWORKSPACEGAP; - const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || + const auto XDISTANCE = m_sActiveSwipe.pMonitor->vecSize.x + *PWORKSPACEGAP; + const auto YDISTANCE = m_sActiveSwipe.pMonitor->vecSize.y + *PWORKSPACEGAP; + const bool VERTANIMS = m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle == "slidevert" || m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.getConfig()->pValues->internalStyle.starts_with("slidefadevert"); m_sActiveSwipe.delta += VERTANIMS ? (*PSWIPEINVR ? -e->dy : e->dy) : (*PSWIPEINVR ? -e->dx : e->dx); @@ -251,11 +251,9 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp( - Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE)); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp( - Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0)); g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); return; @@ -277,15 +275,11 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { } if (VERTANIMS) { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D( - 0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE - YDISTANCE)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp( - Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE - YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE)); } else { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D( - ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE - XDISTANCE, 0)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp( - Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE - XDISTANCE, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0)); } g_pCompositor->updateWorkspaceWindowDecos(workspaceIDLeft); @@ -297,11 +291,9 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { g_pHyprRenderer->damageMonitor(m_sActiveSwipe.pMonitor); if (VERTANIMS) - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp( - Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE)); else - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp( - Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0)); g_pCompositor->updateWorkspaceWindowDecos(m_sActiveSwipe.pWorkspaceBegin->m_iID); return; @@ -323,15 +315,11 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { } if (VERTANIMS) { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D( - 0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE + YDISTANCE)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp( - Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE + YDISTANCE)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(0, ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * YDISTANCE)); } else { - PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D( - ((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE + XDISTANCE, 0)); - m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp( - Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0)); + PWORKSPACE->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE + XDISTANCE, 0)); + m_sActiveSwipe.pWorkspaceBegin->m_vRenderOffset.setValueAndWarp(Vector2D(((-m_sActiveSwipe.delta) / *PSWIPEDIST) * XDISTANCE, 0)); } g_pCompositor->updateWorkspaceWindowDecos(workspaceIDRight); diff --git a/src/plugins/HookSystem.hpp b/src/plugins/HookSystem.hpp index b871a379..00494733 100644 --- a/src/plugins/HookSystem.hpp +++ b/src/plugins/HookSystem.hpp @@ -14,10 +14,10 @@ class CFunctionHook { bool hook(); bool unhook(); - CFunctionHook(const CFunctionHook&) = delete; - CFunctionHook(CFunctionHook&&) = delete; + CFunctionHook(const CFunctionHook&) = delete; + CFunctionHook(CFunctionHook&&) = delete; CFunctionHook& operator=(const CFunctionHook&) = delete; - CFunctionHook& operator=(CFunctionHook&&) = delete; + CFunctionHook& operator=(CFunctionHook&&) = delete; void* m_pOriginal = nullptr; diff --git a/src/protocols/FractionalScale.cpp b/src/protocols/FractionalScale.cpp index f284dd0d..86b5afbc 100644 --- a/src/protocols/FractionalScale.cpp +++ b/src/protocols/FractionalScale.cpp @@ -53,7 +53,9 @@ void CFractionalScaleProtocolManager::bindManager(wl_client* client, void* data, static void handleDestroyScaleAddon(wl_client* client, wl_resource* resource); // -static const struct wp_fractional_scale_v1_interface fractionalScaleAddonImpl { .destroy = handleDestroyScaleAddon }; +static const struct wp_fractional_scale_v1_interface fractionalScaleAddonImpl { + .destroy = handleDestroyScaleAddon +}; // SFractionalScaleAddon* addonFromResource(wl_resource* resource) { diff --git a/src/protocols/Screencopy.hpp b/src/protocols/Screencopy.hpp index e3d1e22a..0c709c7b 100644 --- a/src/protocols/Screencopy.hpp +++ b/src/protocols/Screencopy.hpp @@ -10,8 +10,7 @@ class CMonitor; -enum eClientOwners -{ +enum eClientOwners { CLIENT_SCREENCOPY = 0, CLIENT_TOPLEVEL_EXPORT }; diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index 01e05af1..cd52fe3e 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -30,8 +30,7 @@ inline const float fullVerts[] = { }; inline const float fanVertsFull[] = {-1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f}; -enum eDiscardMode -{ +enum eDiscardMode { DISCARD_OPAQUE = 1, DISCARD_ALPHA = 1 << 1 }; diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index aaafa257..a832802e 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -13,23 +13,20 @@ struct SMonitorRule; // TODO: add fuller damage tracking for updating only parts of a window -enum DAMAGETRACKINGMODES -{ +enum DAMAGETRACKINGMODES { DAMAGE_TRACKING_INVALID = -1, DAMAGE_TRACKING_NONE = 0, DAMAGE_TRACKING_MONITOR, DAMAGE_TRACKING_FULL }; -enum eRenderPassMode -{ +enum eRenderPassMode { RENDER_PASS_ALL = 0, RENDER_PASS_MAIN, RENDER_PASS_POPUP }; -enum eRenderMode -{ +enum eRenderMode { RENDER_MODE_NORMAL = 0, RENDER_MODE_FULL_FAKE = 1, RENDER_MODE_TO_BUFFER = 2, diff --git a/src/render/Texture.hpp b/src/render/Texture.hpp index f287089b..93a6aa5f 100644 --- a/src/render/Texture.hpp +++ b/src/render/Texture.hpp @@ -2,8 +2,7 @@ #include "../defines.hpp" -enum TEXTURETYPE -{ +enum TEXTURETYPE { TEXTURE_INVALID, // Invalid TEXTURE_RGBA, // 4 channels TEXTURE_RGBX, // discard A diff --git a/src/render/decorations/DecorationPositioner.hpp b/src/render/decorations/DecorationPositioner.hpp index 740b4efe..140ecace 100644 --- a/src/render/decorations/DecorationPositioner.hpp +++ b/src/render/decorations/DecorationPositioner.hpp @@ -9,14 +9,12 @@ class CWindow; class IHyprWindowDecoration; -enum eDecorationPositioningPolicy -{ +enum eDecorationPositioningPolicy { DECORATION_POSITION_ABSOLUTE = 0, /* Decoration wants absolute positioning */ DECORATION_POSITION_STICKY, /* Decoration is stuck to some edge of a window */ }; -enum eDecorationEdges -{ +enum eDecorationEdges { DECORATION_EDGE_TOP = 1 << 0, DECORATION_EDGE_BOTTOM = 1 << 1, DECORATION_EDGE_LEFT = 1 << 2, diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp index c411a4d9..15b00536 100644 --- a/src/render/decorations/IHyprWindowDecoration.hpp +++ b/src/render/decorations/IHyprWindowDecoration.hpp @@ -4,24 +4,21 @@ #include "../../helpers/Region.hpp" #include "DecorationPositioner.hpp" -enum eDecorationType -{ +enum eDecorationType { DECORATION_NONE = -1, DECORATION_GROUPBAR, DECORATION_SHADOW, DECORATION_CUSTOM }; -enum eDecorationLayer -{ +enum eDecorationLayer { DECORATION_LAYER_BOTTOM = 0, /* lowest. */ DECORATION_LAYER_UNDER, /* under the window, but above BOTTOM */ DECORATION_LAYER_OVER, /* above the window, but below its popups */ DECORATION_LAYER_OVERLAY /* above everything of the window, including popups */ }; -enum eDecorationFlags -{ +enum eDecorationFlags { DECORATION_ALLOWS_MOUSE_INPUT = 1 << 0, /* this decoration accepts mouse input */ DECORATION_PART_OF_MAIN_WINDOW = 1 << 1, /* this decoration is a *seamless* part of the main window, so stuff like shadows will include it */ DECORATION_NON_SOLID = 1 << 2, /* this decoration is not solid. Other decorations should draw on top of it. Example: shadow */ From 62a8d0be5c1959ade8410f8f964e362288f22175 Mon Sep 17 00:00:00 2001 From: ddmetz <77217897+ddmetz@users.noreply.github.com> Date: Wed, 6 Dec 2023 17:09:25 -0700 Subject: [PATCH 347/513] keybinds: check for null last monitor in changeworkspace (#4077) --- src/managers/KeybindManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index c61ad82e..9bf05a35 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -801,6 +801,10 @@ void CKeybindManager::changeworkspace(std::string args) { static auto* const PWORKSPACECENTERON = &g_pConfigManager->getConfigValuePtr("binds:workspace_center_on")->intValue; const auto PMONITOR = g_pCompositor->m_pLastMonitor; + + if (!PMONITOR) + return; + const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); const bool EXPLICITPREVIOUS = args.starts_with("previous"); From d36055054651442db19df046cbdd0697b805c541 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Thu, 7 Dec 2023 10:41:09 +0000 Subject: [PATCH 348/513] hyprpm: Add hyprpm, a Hyprland Plugin Manager (#4072) --- .github/workflows/ci.yaml | 6 +- .github/workflows/security-checks.yml | 2 +- CMakeLists.txt | 3 +- Makefile | 2 + hyprpm/CMakeLists.txt | 14 + hyprpm/src/core/DataState.cpp | 215 ++++++++ hyprpm/src/core/DataState.hpp | 21 + hyprpm/src/core/Manifest.cpp | 104 ++++ hyprpm/src/core/Manifest.hpp | 32 ++ hyprpm/src/core/Plugin.hpp | 17 + hyprpm/src/core/PluginManager.cpp | 690 ++++++++++++++++++++++++++ hyprpm/src/core/PluginManager.hpp | 59 +++ hyprpm/src/helpers/Colors.hpp | 11 + hyprpm/src/main.cpp | 144 ++++++ hyprpm/src/meson.build | 10 + hyprpm/src/progress/CProgressBar.cpp | 80 +++ hyprpm/src/progress/CProgressBar.hpp | 17 + meson.build | 1 + nix/default.nix | 8 +- 19 files changed, 1428 insertions(+), 8 deletions(-) create mode 100644 hyprpm/CMakeLists.txt create mode 100644 hyprpm/src/core/DataState.cpp create mode 100644 hyprpm/src/core/DataState.hpp create mode 100644 hyprpm/src/core/Manifest.cpp create mode 100644 hyprpm/src/core/Manifest.hpp create mode 100644 hyprpm/src/core/Plugin.hpp create mode 100644 hyprpm/src/core/PluginManager.cpp create mode 100644 hyprpm/src/core/PluginManager.hpp create mode 100644 hyprpm/src/helpers/Colors.hpp create mode 100644 hyprpm/src/main.cpp create mode 100644 hyprpm/src/meson.build create mode 100644 hyprpm/src/progress/CProgressBar.cpp create mode 100644 hyprpm/src/progress/CProgressBar.hpp diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 54248e3a..e68dc2a8 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -12,7 +12,7 @@ jobs: run: | sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf pacman --noconfirm --noprogressbar -Syyu - pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd python libliftoff + pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd python libliftoff tomlplusplus - name: Set up user run: | useradd -m githubuser @@ -61,7 +61,7 @@ jobs: run: | sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf pacman --noconfirm --noprogressbar -Syyu - pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd cmake jq python libliftoff + pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd cmake jq python libliftoff tomlplusplus - name: Set up user run: | useradd -m githubuser @@ -90,7 +90,7 @@ jobs: run: | sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf pacman --noconfirm --noprogressbar -Syyu - pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd libliftoff + pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd libliftoff tomlplusplus - name: Set up user run: | useradd -m githubuser diff --git a/.github/workflows/security-checks.yml b/.github/workflows/security-checks.yml index 6b7d71e5..644aa29d 100644 --- a/.github/workflows/security-checks.yml +++ b/.github/workflows/security-checks.yml @@ -54,7 +54,7 @@ jobs: run: | sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf pacman --noconfirm --noprogressbar -Syyu - pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd python libliftoff + pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd python libliftoff tomlplusplus useradd -m githubuser echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar" diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f52c554..bedb7bbf 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -245,5 +245,6 @@ protocol("staging/tearing-control/tearing-control-v1.xml" "tearing-control-v1" f protocol("unstable/text-input/text-input-unstable-v1.xml" "text-input-unstable-v1" false) protocol("staging/cursor-shape/cursor-shape-v1.xml" "cursor-shape-v1" false) -# hyprctl +# tools add_subdirectory(hyprctl) +add_subdirectory(hyprpm) diff --git a/Makefile b/Makefile index 6213102e..f03931fe 100644 --- a/Makefile +++ b/Makefile @@ -38,8 +38,10 @@ install: mkdir -p ${PREFIX}/bin cp -f ./build/Hyprland ${PREFIX}/bin cp -f ./build/hyprctl/hyprctl ${PREFIX}/bin + cp -f ./build/hyprpm/hyprpm ${PREFIX}/bin chmod 755 ${PREFIX}/bin/Hyprland chmod 755 ${PREFIX}/bin/hyprctl + chmod 755 ${PREFIX}/bin/hyprpm if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi mkdir -p ${PREFIX}/share/hyprland cp ./assets/wall_* ${PREFIX}/share/hyprland diff --git a/hyprpm/CMakeLists.txt b/hyprpm/CMakeLists.txt new file mode 100644 index 00000000..e9cbefa1 --- /dev/null +++ b/hyprpm/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.19) + +project( + hyprpm + DESCRIPTION "A Hyprland Plugin Manager" +) + +file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp") + +set(CMAKE_CXX_STANDARD 23) + +pkg_check_modules(deps REQUIRED IMPORTED_TARGET tomlplusplus) + +add_executable(hyprpm ${SRCFILES}) diff --git a/hyprpm/src/core/DataState.cpp b/hyprpm/src/core/DataState.cpp new file mode 100644 index 00000000..d95f10bb --- /dev/null +++ b/hyprpm/src/core/DataState.cpp @@ -0,0 +1,215 @@ +#include "DataState.hpp" +#include +#include +#include +#include +#include "PluginManager.hpp" + +std::string DataState::getDataStatePath() { + const auto HOME = getenv("HOME"); + if (!HOME) { + std::cerr << "DataState: no $HOME\n"; + throw std::runtime_error("no $HOME"); + return ""; + } + + const auto XDG_DATA_HOME = getenv("XDG_DATA_HOME"); + + if (XDG_DATA_HOME) + return std::string{XDG_DATA_HOME} + "/hyprpm"; + return std::string{HOME} + "/.local/share/hyprpm"; +} + +void DataState::ensureStateStoreExists() { + const auto PATH = getDataStatePath(); + + if (!std::filesystem::exists(PATH)) + std::filesystem::create_directories(PATH); +} + +void DataState::addNewPluginRepo(const SPluginRepository& repo) { + ensureStateStoreExists(); + + const auto PATH = getDataStatePath() + "/" + repo.name; + + std::filesystem::create_directories(PATH); + // clang-format off + auto DATA = toml::table{ + {"repository", toml::table{ + {"name", repo.name}, + {"hash", repo.hash}, + {"url", repo.url} + }} + }; + for (auto& p : repo.plugins) { + // copy .so to the good place + std::filesystem::copy_file(p.filename, PATH + "/" + p.name + ".so"); + + DATA.emplace(p.name, toml::table{ + {"filename", p.name + ".so"}, + {"enabled", p.enabled} + }); + } + // clang-format on + + std::ofstream ofs(PATH + "/state.toml", std::ios::trunc); + ofs << DATA; + ofs.close(); +} + +bool DataState::pluginRepoExists(const std::string& urlOrName) { + ensureStateStoreExists(); + + const auto PATH = getDataStatePath(); + + for (const auto& entry : std::filesystem::directory_iterator(PATH)) { + if (!entry.is_directory()) + continue; + + auto STATE = toml::parse_file(entry.path().string() + "/state.toml"); + + const auto NAME = STATE["repository"]["name"].value_or(""); + const auto URL = STATE["repository"]["url"].value_or(""); + + if (URL == urlOrName || NAME == urlOrName) + return true; + } + + return false; +} + +void DataState::removePluginRepo(const std::string& urlOrName) { + ensureStateStoreExists(); + + const auto PATH = getDataStatePath(); + + for (const auto& entry : std::filesystem::directory_iterator(PATH)) { + if (!entry.is_directory()) + continue; + + auto STATE = toml::parse_file(entry.path().string() + "/state.toml"); + + const auto NAME = STATE["repository"]["name"].value_or(""); + const auto URL = STATE["repository"]["url"].value_or(""); + + if (URL == urlOrName || NAME == urlOrName) { + + // unload the plugins!! + for (const auto& file : std::filesystem::directory_iterator(entry.path())) { + if (!file.path().string().ends_with(".so")) + continue; + + g_pPluginManager->loadUnloadPlugin(std::filesystem::absolute(file.path()), false); + } + + std::filesystem::remove_all(entry.path()); + return; + } + } +} + +void DataState::updateGlobalState(const SGlobalState& state) { + ensureStateStoreExists(); + + const auto PATH = getDataStatePath(); + + std::filesystem::create_directories(PATH); + // clang-format off + auto DATA = toml::table{ + {"state", toml::table{ + {"hash", state.headersHashCompiled}, + {"dont_warn_install", state.dontWarnInstall} + }} + }; + // clang-format on + + std::ofstream ofs(PATH + "/state.toml", std::ios::trunc); + ofs << DATA; + ofs.close(); +} + +SGlobalState DataState::getGlobalState() { + ensureStateStoreExists(); + + const auto PATH = getDataStatePath(); + + if (!std::filesystem::exists(PATH + "/state.toml")) + return SGlobalState{}; + + auto DATA = toml::parse_file(PATH + "/state.toml"); + + SGlobalState state; + state.headersHashCompiled = DATA["state"]["hash"].value_or(""); + state.dontWarnInstall = DATA["state"]["dont_warn_install"].value_or(false); + + return state; +} + +std::vector DataState::getAllRepositories() { + ensureStateStoreExists(); + + const auto PATH = getDataStatePath(); + + std::vector repos; + + for (const auto& entry : std::filesystem::directory_iterator(PATH)) { + if (!entry.is_directory()) + continue; + + auto STATE = toml::parse_file(entry.path().string() + "/state.toml"); + + const auto NAME = STATE["repository"]["name"].value_or(""); + const auto URL = STATE["repository"]["url"].value_or(""); + const auto HASH = STATE["repository"]["hash"].value_or(""); + + SPluginRepository repo; + repo.hash = HASH; + repo.name = NAME; + repo.url = URL; + + for (const auto& [key, val] : STATE) { + if (key == "repository") + continue; + + const auto ENABLED = STATE[key]["enabled"].value_or(false); + const auto FILENAME = STATE[key]["filename"].value_or(""); + + repo.plugins.push_back(SPlugin{std::string{key.str()}, FILENAME, ENABLED}); + } + + repos.push_back(repo); + } + + return repos; +} + +bool DataState::setPluginEnabled(const std::string& name, bool enabled) { + ensureStateStoreExists(); + + const auto PATH = getDataStatePath(); + + for (const auto& entry : std::filesystem::directory_iterator(PATH)) { + if (!entry.is_directory()) + continue; + + auto STATE = toml::parse_file(entry.path().string() + "/state.toml"); + + for (const auto& [key, val] : STATE) { + if (key == "repository") + continue; + + if (key.str() != name) + continue; + + (*STATE[key].as_table()).insert_or_assign("enabled", enabled); + + std::ofstream state(entry.path().string() + "/state.toml", std::ios::trunc); + state << STATE; + state.close(); + + return true; + } + } + + return false; +} \ No newline at end of file diff --git a/hyprpm/src/core/DataState.hpp b/hyprpm/src/core/DataState.hpp new file mode 100644 index 00000000..ac81dae1 --- /dev/null +++ b/hyprpm/src/core/DataState.hpp @@ -0,0 +1,21 @@ +#pragma once +#include +#include +#include "Plugin.hpp" + +struct SGlobalState { + std::string headersHashCompiled = ""; + bool dontWarnInstall = false; +}; + +namespace DataState { + std::string getDataStatePath(); + void ensureStateStoreExists(); + void addNewPluginRepo(const SPluginRepository& repo); + void removePluginRepo(const std::string& urlOrName); + bool pluginRepoExists(const std::string& urlOrName); + void updateGlobalState(const SGlobalState& state); + SGlobalState getGlobalState(); + bool setPluginEnabled(const std::string& name, bool enabled); + std::vector getAllRepositories(); +}; \ No newline at end of file diff --git a/hyprpm/src/core/Manifest.cpp b/hyprpm/src/core/Manifest.cpp new file mode 100644 index 00000000..27ad058a --- /dev/null +++ b/hyprpm/src/core/Manifest.cpp @@ -0,0 +1,104 @@ +#include "Manifest.hpp" +#include +#include + +CManifest::CManifest(const eManifestType type, const std::string& path) { + auto manifest = toml::parse_file(path); + + if (type == MANIFEST_HYPRLOAD) { + for (auto& [key, val] : manifest) { + if (key.str().ends_with(".build")) + continue; + + CManifest::SManifestPlugin plugin; + plugin.name = key; + m_vPlugins.push_back(plugin); + } + + for (auto& plugin : m_vPlugins) { + plugin.description = manifest[plugin.name]["description"].value_or("?"); + plugin.version = manifest[plugin.name]["version"].value_or("?"); + plugin.output = manifest[plugin.name]["build"]["output"].value_or("?"); + auto authors = manifest[plugin.name]["authors"].as_array(); + if (authors) { + for (auto&& a : *authors) { + plugin.authors.push_back(a.as_string()->value_or("?")); + } + } else { + auto author = manifest[plugin.name]["author"].value_or(""); + if (!std::string{author}.empty()) + plugin.authors.push_back(author); + } + auto buildSteps = manifest[plugin.name]["build"]["steps"].as_array(); + if (buildSteps) { + for (auto&& s : *buildSteps) { + plugin.buildSteps.push_back(s.as_string()->value_or("?")); + } + } + + if (plugin.output.empty() || plugin.buildSteps.empty()) { + m_bGood = false; + return; + } + } + } else if (type == MANIFEST_HYPRPM) { + m_sRepository.name = manifest["repository"]["name"].value_or(""); + auto authors = manifest["repository"]["authors"].as_array(); + if (authors) { + for (auto&& a : *authors) { + m_sRepository.authors.push_back(a.as_string()->value_or("?")); + } + } else { + auto author = manifest["repository"]["author"].value_or(""); + if (!std::string{author}.empty()) + m_sRepository.authors.push_back(author); + } + + auto pins = manifest["repository"]["commit_pins"].as_array(); + if (pins) { + for (auto&& pin : *pins) { + auto pinArr = pin.as_array(); + if (pinArr && pinArr->get(1)) + m_sRepository.commitPins.push_back(std::make_pair<>(pinArr->get(0)->as_string()->get(), pinArr->get(1)->as_string()->get())); + } + } + + for (auto& [key, val] : manifest) { + if (key.str() == "repository") + continue; + + CManifest::SManifestPlugin plugin; + plugin.name = key; + m_vPlugins.push_back(plugin); + } + + for (auto& plugin : m_vPlugins) { + plugin.description = manifest[plugin.name]["description"].value_or("?"); + plugin.output = manifest[plugin.name]["output"].value_or("?"); + auto authors = manifest[plugin.name]["authors"].as_array(); + if (authors) { + for (auto&& a : *authors) { + plugin.authors.push_back(a.as_string()->value_or("?")); + } + } else { + auto author = manifest[plugin.name]["author"].value_or(""); + if (!std::string{author}.empty()) + plugin.authors.push_back(author); + } + auto buildSteps = manifest[plugin.name]["build"].as_array(); + if (buildSteps) { + for (auto&& s : *buildSteps) { + plugin.buildSteps.push_back(s.as_string()->value_or("?")); + } + } + + if (plugin.output.empty() || plugin.buildSteps.empty()) { + m_bGood = false; + return; + } + } + } else { + // ??? + m_bGood = false; + } +} \ No newline at end of file diff --git a/hyprpm/src/core/Manifest.hpp b/hyprpm/src/core/Manifest.hpp new file mode 100644 index 00000000..63e1791f --- /dev/null +++ b/hyprpm/src/core/Manifest.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include + +enum eManifestType { + MANIFEST_HYPRLOAD, + MANIFEST_HYPRPM +}; + +class CManifest { + public: + CManifest(const eManifestType type, const std::string& path); + + struct SManifestPlugin { + std::string name; + std::string description; + std::string version; + std::vector authors; + std::vector buildSteps; + std::string output; + }; + + struct { + std::string name; + std::vector authors; + std::vector> commitPins; + } m_sRepository; + + std::vector m_vPlugins; + bool m_bGood = true; +}; \ No newline at end of file diff --git a/hyprpm/src/core/Plugin.hpp b/hyprpm/src/core/Plugin.hpp new file mode 100644 index 00000000..32c02a49 --- /dev/null +++ b/hyprpm/src/core/Plugin.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +struct SPlugin { + std::string name; + std::string filename; + bool enabled; +}; + +struct SPluginRepository { + std::string url; + std::string name; + std::vector plugins; + std::string hash; +}; \ No newline at end of file diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp new file mode 100644 index 00000000..8efcdf98 --- /dev/null +++ b/hyprpm/src/core/PluginManager.cpp @@ -0,0 +1,690 @@ +#include "PluginManager.hpp" +#include "../helpers/Colors.hpp" +#include "../progress/CProgressBar.hpp" +#include "Manifest.hpp" +#include "DataState.hpp" + +#include +#include +#include +#include +#include +#include + +#include + +std::string execAndGet(std::string cmd) { + cmd += " 2>&1"; + std::array buffer; + std::string result; + const std::unique_ptr pipe(popen(cmd.c_str(), "r"), pclose); + if (!pipe) + return ""; + + while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { + result += buffer.data(); + } + return result; +} + +SHyprlandVersion CPluginManager::getHyprlandVersion() { + static SHyprlandVersion ver; + static bool once = false; + + if (once) + return ver; + + once = true; + const auto HLVERCALL = execAndGet("hyprctl version"); + if (m_bVerbose) + std::cout << Colors::BLUE << "[v] " << Colors::RESET << "version returned: " << HLVERCALL << "\n"; + + if (!HLVERCALL.contains("Tag:")) { + std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " You don't seem to be running Hyprland."; + return SHyprlandVersion{}; + } + + std::string hlcommit = HLVERCALL.substr(HLVERCALL.find("at commit") + 10); + hlcommit = hlcommit.substr(0, hlcommit.find_first_of(' ')); + + std::string hlbranch = HLVERCALL.substr(HLVERCALL.find("from branch") + 12); + hlbranch = hlbranch.substr(0, hlbranch.find(" at commit ")); + + if (m_bVerbose) + std::cout << Colors::BLUE << "[v] " << Colors::RESET << "parsed commit " << hlcommit << " at branch " << hlbranch << "\n"; + + ver = SHyprlandVersion{hlbranch, hlcommit}; + return ver; +} + +bool CPluginManager::addNewPluginRepo(const std::string& url) { + + if (DataState::pluginRepoExists(url)) { + std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. Repository already installed.\n"; + return false; + } + + auto GLOBALSTATE = DataState::getGlobalState(); + if (!GLOBALSTATE.dontWarnInstall) { + std::cout << Colors::YELLOW << "!" << Colors::RED << " Disclaimer:\n " << Colors::RESET + << "plugins, especially not official, have no guarantee of stability, availablity or security.\n Run them at your own risk.\n " + << "This message will not appear again.\n"; + GLOBALSTATE.dontWarnInstall = true; + DataState::updateGlobalState(GLOBALSTATE); + } + + std::cout << Colors::GREEN << "✔" << Colors::RESET << Colors::RED << " adding a new plugin repository " << Colors::RESET << "from " << url << "\n " << Colors::RED + << "MAKE SURE" << Colors::RESET << " that you trust the authors. " << Colors::RED << "DO NOT" << Colors::RESET + << " install random plugins without verifying the code and author.\n " + << "Are you sure? [Y/n] "; + std::fflush(stdout); + std::string input; + std::getline(std::cin, input); + + if (input.size() > 0 && input[0] != 'Y' && input[0] != 'y') { + std::cout << "Aborting.\n"; + return false; + } + + CProgressBar progress; + progress.m_iMaxSteps = 5; + progress.m_iSteps = 0; + progress.m_szCurrentMessage = "Cloning the plugin repository"; + + progress.print(); + + if (!std::filesystem::exists("/tmp/hyprpm")) { + std::filesystem::create_directory("/tmp/hyprpm"); + std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace); + } + + if (std::filesystem::exists("/tmp/hyprpm/new")) { + progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " old plugin repo build files found in temp directory, removing."); + std::filesystem::remove_all("/tmp/hyprpm/new"); + } + + progress.printMessageAbove(std::string{Colors::RESET} + " → Cloning " + url); + + std::string ret = execAndGet("cd /tmp/hyprpm && git clone " + url + " new"); + + if (!std::filesystem::exists("/tmp/hyprpm/new")) { + std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. shell returned:\n" << ret << "\n"; + return false; + } + + progress.m_iSteps = 1; + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " cloned"); + progress.m_szCurrentMessage = "Reading the manifest"; + progress.print(); + + std::unique_ptr pManifest; + + if (std::filesystem::exists("/tmp/hyprpm/new/hyprpm.toml")) { + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprpm manifest"); + pManifest = std::make_unique(MANIFEST_HYPRPM, "/tmp/hyprpm/new/hyprpm.toml"); + } else if (std::filesystem::exists("/tmp/hyprpm/new/hyprload.toml")) { + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprload manifest"); + pManifest = std::make_unique(MANIFEST_HYPRLOAD, "/tmp/hyprpm/new/hyprload.toml"); + } + + if (!pManifest) { + std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository does not have a valid manifest\n"; + return false; + } + + if (!pManifest->m_bGood) { + std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository has a corrupted manifest\n"; + return false; + } + + progress.m_iSteps = 2; + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " parsed manifest, found " + std::to_string(pManifest->m_vPlugins.size()) + " plugins:"); + for (auto& pl : pManifest->m_vPlugins) { + std::string message = std::string{Colors::RESET} + " → " + pl.name + " by "; + for (auto& a : pl.authors) { + message += a + ", "; + } + if (pl.authors.size() > 0) { + message.pop_back(); + message.pop_back(); + } + message += " version " + pl.version; + progress.printMessageAbove(message); + } + progress.m_szCurrentMessage = "Verifying headers"; + progress.print(); + + const auto HEADERSSTATUS = headersValid(); + + if (HEADERSSTATUS != HEADERS_OK) { + + switch (HEADERSSTATUS) { + case HEADERS_CORRUPTED: std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Headers corrupted. Please run hyprpm update to fix those.\n"; break; + case HEADERS_MISMATCHED: std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Headers version mismatch. Please run hyprpm update to fix those.\n"; break; + case HEADERS_NOT_HYPRLAND: std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " It doesn't seem you are running on hyprland.\n"; break; + case HEADERS_MISSING: std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Headers missing. Please run hyprpm update to fix those.\n"; break; + default: break; + } + + return false; + } + + progress.m_iSteps = 3; + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " Hyprland headers OK"); + progress.m_szCurrentMessage = "Building plugin(s)"; + progress.print(); + + for (auto& p : pManifest->m_vPlugins) { + std::string out; + + progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name); + + for (auto& bs : p.buildSteps) { + out += execAndGet("cd /tmp/hyprpm/new && " + bs) + "\n"; + } + + if (!std::filesystem::exists("/tmp/hyprpm/new/" + p.output)) { + std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Plugin " << p.name << " failed to build.\n"; + + if (m_bVerbose) + std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n"; + + return false; + } + + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " built " + p.name + " into " + p.output); + } + + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " all plugins built"); + progress.m_iSteps = 4; + progress.m_szCurrentMessage = "Installing repository"; + progress.print(); + + // add repo toml to DataState + SPluginRepository repo; + std::string repohash = execAndGet("cd /tmp/hyprpm/new/ && git rev-parse HEAD"); + if (repohash.length() > 0) + repohash.pop_back(); + repo.name = pManifest->m_sRepository.name.empty() ? url.substr(url.find_last_of('/') + 1) : pManifest->m_sRepository.name; + repo.url = url; + repo.hash = repohash; + for (auto& p : pManifest->m_vPlugins) { + repo.plugins.push_back(SPlugin{p.name, "/tmp/hyprpm/new/" + p.output, false}); + } + DataState::addNewPluginRepo(repo); + + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " installed repository"); + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " you can now enable the plugin(s) with hyprpm enable"); + progress.m_iSteps = 5; + progress.m_szCurrentMessage = "Done!"; + progress.print(); + + std::cout << "\n"; + + // remove build files + std::filesystem::remove_all("/tmp/hyprpm/new"); + + return true; +} + +bool CPluginManager::removePluginRepo(const std::string& urlOrName) { + if (!DataState::pluginRepoExists(urlOrName)) { + std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not remove the repository. Repository is not installed.\n"; + return false; + } + + std::cout << Colors::YELLOW << "!" << Colors::RESET << Colors::RED << " removing a plugin repository: " << Colors::RESET << urlOrName << "\n " + << "Are you sure? [Y/n] "; + std::fflush(stdout); + std::string input; + std::getline(std::cin, input); + + if (input.size() > 0 && input[0] != 'Y' && input[0] != 'y') { + std::cout << "Aborting.\n"; + return false; + } + + DataState::removePluginRepo(urlOrName); + + return true; +} + +eHeadersErrors CPluginManager::headersValid() { + const auto HLVER = getHyprlandVersion(); + + // find headers commit + auto headers = execAndGet("pkg-config --cflags hyprland"); + + if (!headers.contains("-I/")) + return HEADERS_MISSING; + + headers.pop_back(); // pop newline + + std::string verHeader = ""; + + while (!headers.empty()) { + const auto PATH = headers.substr(0, headers.find(" -I/", 3)); + + if (headers.find(" -I/", 3) != std::string::npos) + headers = headers.substr(headers.find("-I/", 3)); + else + headers = ""; + + if (PATH.ends_with("protocols") || PATH.ends_with("wlroots")) + continue; + + verHeader = PATH.substr(2) + "/hyprland/src/version.h"; + break; + } + + if (verHeader.empty()) + return HEADERS_CORRUPTED; + + // read header + std::ifstream ifs(verHeader); + if (!ifs.good()) + return HEADERS_CORRUPTED; + + std::string verHeaderContent((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); + ifs.close(); + + std::string hash = verHeaderContent.substr(verHeaderContent.find("#define GIT_COMMIT_HASH") + 23); + hash = hash.substr(0, hash.find_first_of('\n')); + hash = hash.substr(hash.find_first_of('"') + 1); + hash = hash.substr(0, hash.find_first_of('"')); + + if (hash != HLVER.hash) + return HEADERS_MISMATCHED; + + return HEADERS_OK; +} + +bool CPluginManager::updateHeaders() { + + const auto HLVER = getHyprlandVersion(); + + if (!std::filesystem::exists("/tmp/hyprpm")) { + std::filesystem::create_directory("/tmp/hyprpm"); + std::filesystem::permissions("/tmp/hyprpm", std::filesystem::perms::all, std::filesystem::perm_options::replace); + } + + if (headersValid() == HEADERS_OK) { + std::cout << "\n" << std::string{Colors::GREEN} + "✔" + Colors::RESET + " Your headers are already up-to-date.\n"; + auto GLOBALSTATE = DataState::getGlobalState(); + GLOBALSTATE.headersHashCompiled = HLVER.hash; + DataState::updateGlobalState(GLOBALSTATE); + return true; + } + + CProgressBar progress; + progress.m_iMaxSteps = 5; + progress.m_iSteps = 0; + progress.m_szCurrentMessage = "Cloning the hyprland repository"; + progress.print(); + + if (std::filesystem::exists("/tmp/hyprpm/hyprland")) { + progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " old hyprland source files found in temp directory, removing."); + std::filesystem::remove_all("/tmp/hyprpm/hyprland"); + } + + progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " Cloning https://github.com/hyprwm/hyprland, this might take a moment."); + + std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive https://github.com/hyprwm/hyprland hyprland"); + + if (!std::filesystem::exists("/tmp/hyprpm/hyprland")) { + std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the hyprland repository. shell returned:\n" << ret << "\n"; + return false; + } + + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " cloned"); + progress.m_iSteps = 2; + progress.m_szCurrentMessage = "Checking out sources"; + progress.print(); + + ret = + execAndGet("cd /tmp/hyprpm/hyprland && git checkout " + HLVER.branch + " 2>&1 && git submodule update --init 2>&1 && git reset --hard --recurse-submodules " + HLVER.hash); + + if (m_bVerbose) + progress.printMessageAbove(std::string{Colors::BLUE} + "[v] " + Colors::RESET + "git returned: " + ret); + + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " checked out to running ver"); + progress.m_iSteps = 3; + progress.m_szCurrentMessage = "Building Hyprland"; + progress.print(); + + progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " configuring Hyprland"); + + ret = execAndGet("cd /tmp/hyprpm/hyprland && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -S . -B ./build -G Ninja"); + // le hack. Wlroots has to generate its build/include + ret = execAndGet("cd /tmp/hyprpm/hyprland/subprojects/wlroots && meson setup -Drenderers=gles2 -Dexamples=false build"); + + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " configured Hyprland"); + progress.m_iSteps = 4; + progress.m_szCurrentMessage = "Installing sources"; + progress.print(); + + progress.printMessageAbove( + std::string{Colors::YELLOW} + "!" + Colors::RESET + + " in order to install the sources, you will need to input your password.\n If nothing pops up, make sure you have polkit and an authentication daemon running."); + + ret = execAndGet("pkexec sh \"-c\" \"cd /tmp/hyprpm/hyprland && make installheaders\""); + + if (m_bVerbose) + std::cout << Colors::BLUE << "[v] " << Colors::RESET << "pkexec returned: " << ret << "\n"; + + // remove build files + std::filesystem::remove_all("/tmp/hyprpm/hyprland"); + + auto HEADERSVALID = headersValid(); + if (HEADERSVALID == HEADERS_OK) { + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " installed headers"); + progress.m_iSteps = 5; + progress.m_szCurrentMessage = "Done!"; + progress.print(); + + auto GLOBALSTATE = DataState::getGlobalState(); + GLOBALSTATE.headersHashCompiled = HLVER.hash; + DataState::updateGlobalState(GLOBALSTATE); + + std::cout << "\n"; + } else { + progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " failed to install headers with error code " + std::to_string((int)HEADERSVALID)); + progress.m_iSteps = 5; + progress.m_szCurrentMessage = "Failed"; + progress.print(); + + std::cout << "\n"; + + return false; + } + + return true; +} + +bool CPluginManager::updatePlugins(bool forceUpdateAll) { + if (headersValid() != HEADERS_OK) { + std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " headers are not up-to-date, please run hyprpm update.\n"; + return false; + } + + const auto REPOS = DataState::getAllRepositories(); + + if (REPOS.size() < 1) { + std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " No repos to update.\n"; + return true; + } + + const auto HLVER = getHyprlandVersion(); + + CProgressBar progress; + progress.m_iMaxSteps = REPOS.size() * 2 + 1; + progress.m_iSteps = 0; + progress.m_szCurrentMessage = "Updating repositories"; + progress.print(); + + for (auto& repo : REPOS) { + bool update = forceUpdateAll; + + progress.m_iSteps++; + progress.m_szCurrentMessage = "Updating " + repo.name; + progress.print(); + + progress.printMessageAbove(std::string{Colors::RESET} + " → checking for updates for " + repo.name); + + if (std::filesystem::exists("/tmp/hyprpm/update")) { + progress.printMessageAbove(std::string{Colors::YELLOW} + "!" + Colors::RESET + " old update build files found in temp directory, removing."); + std::filesystem::remove_all("/tmp/hyprpm/update"); + } + + progress.printMessageAbove(std::string{Colors::RESET} + " → Cloning " + repo.url); + + std::string ret = execAndGet("cd /tmp/hyprpm && git clone " + repo.url + " update"); + + if (!std::filesystem::exists("/tmp/hyprpm/update")) { + std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " could not clone repo: shell returned:\n" + ret; + return false; + } + + if (!update) { + // check if git has updates + std::string hash = execAndGet("cd /tmp/hyprpm/update && git rev-parse HEAD"); + if (!hash.empty()) + hash.pop_back(); + + update = update || hash != repo.hash; + } + + if (!update) { + std::filesystem::remove_all("/tmp/hyprpm/update"); + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " repository " + repo.name + " is up-to-date."); + progress.m_iSteps++; + progress.print(); + continue; + } + + // we need to update + + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " repository " + repo.name + " has updates."); + progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + repo.name); + progress.m_iSteps++; + progress.print(); + + std::unique_ptr pManifest; + + if (std::filesystem::exists("/tmp/hyprpm/update/hyprpm.toml")) { + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprpm manifest"); + pManifest = std::make_unique(MANIFEST_HYPRPM, "/tmp/hyprpm/update/hyprpm.toml"); + } else if (std::filesystem::exists("/tmp/hyprpm/update/hyprload.toml")) { + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " found hyprload manifest"); + pManifest = std::make_unique(MANIFEST_HYPRLOAD, "/tmp/hyprpm/update/hyprload.toml"); + } + + if (!pManifest) { + std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository does not have a valid manifest\n"; + continue; + } + + if (!pManifest->m_bGood) { + std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " The provided plugin repository has a corrupted manifest\n"; + continue; + } + + if (!pManifest->m_sRepository.commitPins.empty()) { + // check commit pins + + progress.printMessageAbove(std::string{Colors::RESET} + " → Manifest has " + std::to_string(pManifest->m_sRepository.commitPins.size()) + " pins, checking"); + + for (auto& [hl, plugin] : pManifest->m_sRepository.commitPins) { + if (hl != HLVER.hash) + continue; + + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " commit pin " + plugin + " matched hl, resetting"); + + execAndGet("cd /tmp/hyprpm/update/ && git reset --hard --recurse-submodules " + plugin); + } + } + + bool failed = false; + for (auto& p : pManifest->m_vPlugins) { + std::string out; + + progress.printMessageAbove(std::string{Colors::RESET} + " → Building " + p.name); + + for (auto& bs : p.buildSteps) { + out += execAndGet("cd /tmp/hyprpm/update && " + bs) + "\n"; + } + + if (!std::filesystem::exists("/tmp/hyprpm/update/" + p.output)) { + std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Plugin " << p.name << " failed to build.\n"; + failed = true; + if (m_bVerbose) + std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n"; + break; + } + + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " built " + p.name + " into " + p.output); + } + + if (failed) + continue; + + // add repo toml to DataState + SPluginRepository newrepo = repo; + newrepo.plugins.clear(); + execAndGet( + "cd /tmp/hyprpm/update/ && git pull --recurse-submodules && git reset --hard --recurse-submodules"); // repo hash in the state.toml has to match head and not any pin + std::string repohash = execAndGet("git rev-parse HEAD"); + if (repohash.length() > 0) + repohash.pop_back(); + newrepo.hash = repohash; + for (auto& p : pManifest->m_vPlugins) { + const auto OLDPLUGINIT = std::find_if(repo.plugins.begin(), repo.plugins.end(), [&](const auto& other) { return other.name == p.name; }); + newrepo.plugins.push_back(SPlugin{p.name, "/tmp/hyprpm/update/" + p.output, OLDPLUGINIT != repo.plugins.end() ? OLDPLUGINIT->enabled : false}); + } + DataState::removePluginRepo(newrepo.name); + DataState::addNewPluginRepo(newrepo); + + std::filesystem::remove_all("/tmp/hyprpm/update"); + + progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " updated " + repo.name); + } + + progress.m_iSteps++; + progress.m_szCurrentMessage = "Done!"; + progress.print(); + + std::cout << "\n"; + + return true; +} + +bool CPluginManager::enablePlugin(const std::string& name) { + bool ret = DataState::setPluginEnabled(name, true); + if (ret) + std::cout << Colors::GREEN << "✔" << Colors::RESET << " Enabled " << name << "\n"; + return ret; +} + +bool CPluginManager::disablePlugin(const std::string& name) { + bool ret = DataState::setPluginEnabled(name, false); + if (ret) + std::cout << Colors::GREEN << "✔" << Colors::RESET << " Disabled " << name << "\n"; + return ret; +} + +ePluginLoadStateReturn CPluginManager::ensurePluginsLoadState() { + if (headersValid() != HEADERS_OK) { + std::cerr << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " headers are not up-to-date, please run hyprpm update.\n"; + return LOADSTATE_HEADERS_OUTDATED; + } + + const auto HOME = getenv("HOME"); + const auto HIS = getenv("HYPRLAND_INSTANCE_SIGNATURE"); + if (!HOME || !HIS) { + std::cerr << "PluginManager: no $HOME or HIS\n"; + return LOADSTATE_FAIL; + } + const auto HYPRPMPATH = DataState::getDataStatePath() + "/"; + + auto pluginLines = execAndGet("hyprctl plugins list | grep Plugin"); + + std::vector loadedPlugins; + + std::cout << Colors::GREEN << "✔" << Colors::RESET << " Ensuring plugin load state\n"; + + // iterate line by line + while (!pluginLines.empty()) { + auto plLine = pluginLines.substr(0, pluginLines.find("\n")); + + if (pluginLines.find("\n") != std::string::npos) + pluginLines = pluginLines.substr(pluginLines.find("\n") + 1); + else + pluginLines = ""; + + if (plLine.back() != ':') + continue; + + plLine = plLine.substr(7); + plLine = plLine.substr(0, plLine.find(" by ")); + + loadedPlugins.push_back(plLine); + } + + // get state + const auto REPOS = DataState::getAllRepositories(); + + auto enabled = [REPOS](const std::string& plugin) -> bool { + for (auto& r : REPOS) { + for (auto& p : r.plugins) { + if (p.name == plugin && p.enabled) + return true; + } + } + + return false; + }; + + auto repoForName = [REPOS](const std::string& name) -> std::string { + for (auto& r : REPOS) { + for (auto& p : r.plugins) { + if (p.name == name) + return r.name; + } + } + + return ""; + }; + + // unload disabled plugins + for (auto& p : loadedPlugins) { + if (!enabled(p)) { + // unload + loadUnloadPlugin(HYPRPMPATH + repoForName(p) + "/" + p + ".so", false); + std::cout << Colors::GREEN << "✔" << Colors::RESET << " Unloaded " << p << "\n"; + } + } + + // load enabled plugins + for (auto& r : REPOS) { + for (auto& p : r.plugins) { + if (!p.enabled) + continue; + + if (std::find_if(loadedPlugins.begin(), loadedPlugins.end(), [&](const auto& other) { return other == p.name; }) != loadedPlugins.end()) + continue; + + loadUnloadPlugin(HYPRPMPATH + repoForName(p.name) + "/" + p.filename, true); + std::cout << Colors::GREEN << "✔" << Colors::RESET << " Loaded " << p.name << "\n"; + } + } + + std::cout << Colors::GREEN << "✔" << Colors::RESET << " Plugin load state ensured\n"; + + return LOADSTATE_OK; +} + +bool CPluginManager::loadUnloadPlugin(const std::string& path, bool load) { + if (load) + execAndGet("hyprctl plugin load " + path); + else + execAndGet("hyprctl plugin unload " + path); + + return true; +} + +void CPluginManager::listAllPlugins() { + const auto REPOS = DataState::getAllRepositories(); + + for (auto& r : REPOS) { + std::cout << std::string{Colors::RESET} + " → Repository " + r.name + ":\n"; + + for (auto& p : r.plugins) { + std::cout << std::string{Colors::RESET} + " │ Plugin " + p.name + "\n └─ enabled: " << (p.enabled ? Colors::GREEN : Colors::RED) << (p.enabled ? "true" : "false") + << Colors::RESET << "\n"; + } + } +} + +void CPluginManager::notify(const eNotifyIcons icon, uint32_t color, int durationMs, const std::string& message) { + execAndGet("hyprctl notify " + std::to_string((int)icon) + " " + std::to_string(durationMs) + " " + std::to_string(color) + " " + message); +} \ No newline at end of file diff --git a/hyprpm/src/core/PluginManager.hpp b/hyprpm/src/core/PluginManager.hpp new file mode 100644 index 00000000..dcf890d6 --- /dev/null +++ b/hyprpm/src/core/PluginManager.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include +#include + +enum eHeadersErrors { + HEADERS_OK = 0, + HEADERS_NOT_HYPRLAND, + HEADERS_MISSING, + HEADERS_CORRUPTED, + HEADERS_MISMATCHED, +}; + +enum eNotifyIcons { + ICON_WARNING = 0, + ICON_INFO, + ICON_HINT, + ICON_ERROR, + ICON_CONFUSED, + ICON_OK, + ICON_NONE +}; + +enum ePluginLoadStateReturn { + LOADSTATE_OK = 0, + LOADSTATE_FAIL, + LOADSTATE_PARTIAL_FAIL, + LOADSTATE_HEADERS_OUTDATED +}; + +struct SHyprlandVersion { + std::string branch; + std::string hash; +}; + +class CPluginManager { + public: + bool addNewPluginRepo(const std::string& url); + bool removePluginRepo(const std::string& urlOrName); + + eHeadersErrors headersValid(); + bool updateHeaders(); + bool updatePlugins(bool forceUpdateAll); + + void listAllPlugins(); + + bool enablePlugin(const std::string& name); + bool disablePlugin(const std::string& name); + ePluginLoadStateReturn ensurePluginsLoadState(); + + bool loadUnloadPlugin(const std::string& path, bool load); + SHyprlandVersion getHyprlandVersion(); + + void notify(const eNotifyIcons icon, uint32_t color, int durationMs, const std::string& message); + + bool m_bVerbose = false; +}; + +inline std::unique_ptr g_pPluginManager; \ No newline at end of file diff --git a/hyprpm/src/helpers/Colors.hpp b/hyprpm/src/helpers/Colors.hpp new file mode 100644 index 00000000..f3298bdd --- /dev/null +++ b/hyprpm/src/helpers/Colors.hpp @@ -0,0 +1,11 @@ +#pragma once + +namespace Colors { + constexpr const char* RED = "\x1b[31m"; + constexpr const char* GREEN = "\x1b[32m"; + constexpr const char* YELLOW = "\x1b[33m"; + constexpr const char* BLUE = "\x1b[34m"; + constexpr const char* MAGENTA = "\x1b[35m"; + constexpr const char* CYAN = "\x1b[36m"; + constexpr const char* RESET = "\x1b[0m"; +}; \ No newline at end of file diff --git a/hyprpm/src/main.cpp b/hyprpm/src/main.cpp new file mode 100644 index 00000000..e6191e66 --- /dev/null +++ b/hyprpm/src/main.cpp @@ -0,0 +1,144 @@ +#include "progress/CProgressBar.hpp" +#include "helpers/Colors.hpp" +#include "core/PluginManager.hpp" + +#include +#include +#include +#include +#include + +const std::string HELP = R"#(┏ hyprpm, a Hyprland Plugin Manager +┃ +┣ add [url] → Install a new plugin repository from git +┣ remove [url/name] → Remove an installed plugin repository +┣ enable [name] → Enable a plugin +┣ disable [name] → Disable a plugin +┣ update → Check and update all plugins if needed +┣ reload → Reload hyprpm state. Ensure all enabled plugins are loaded. +┣ list → List all installed plugins +┃ +┣ Flags: +┃ +┣ --notify | -n → Send a hyprland notification for important events (e.g. load fail) +┣ --help | -h → Show this menu +┣ --verbose | -v → Enable too much logging +┗ +)#"; + +int main(int argc, char** argv, char** envp) { + std::vector ARGS{argc}; + for (int i = 0; i < argc; ++i) { + ARGS[i] = std::string{argv[i]}; + } + + if (ARGS.size() < 2) { + std::cout << HELP; + return 1; + } + + std::vector command; + bool notify = false, verbose = false; + + for (int i = 1; i < argc; ++i) { + if (ARGS[i].starts_with("-")) { + if (ARGS[i] == "--help" || ARGS[i] == "-h") { + std::cout << HELP; + return 0; + } else if (ARGS[i] == "--notify" || ARGS[i] == "-n") { + notify = true; + } else if (ARGS[i] == "--verbose" || ARGS[i] == "-v") { + verbose = true; + } else { + std::cerr << "Unrecognized option " << ARGS[i]; + return 1; + } + } else { + command.push_back(ARGS[i]); + } + } + + g_pPluginManager = std::make_unique(); + g_pPluginManager->m_bVerbose = verbose; + + if (command[0] == "add") { + if (command.size() < 2) { + std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for add.\n"; + return 1; + } + + return g_pPluginManager->addNewPluginRepo(command[1]) ? 0 : 1; + } else if (command[0] == "remove") { + if (ARGS.size() < 2) { + std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for remove.\n"; + return 1; + } + + return g_pPluginManager->removePluginRepo(command[1]) ? 0 : 1; + } else if (command[0] == "update") { + bool headersValid = g_pPluginManager->headersValid() == HEADERS_OK; + bool headers = g_pPluginManager->updateHeaders(); + if (headers) { + bool ret1 = g_pPluginManager->updatePlugins(!headersValid); + + if (!ret1) + return 1; + + auto ret2 = g_pPluginManager->ensurePluginsLoadState(); + + if (ret2 != LOADSTATE_OK) + return 1; + } else if (notify) + g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Couldn't update headers"); + } else if (command[0] == "enable") { + if (ARGS.size() < 2) { + std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for enable.\n"; + return 1; + } + + if (!g_pPluginManager->enablePlugin(command[1])) { + std::cerr << Colors::RED << "✖" << Colors::RESET << " Couldn't enable plugin (missing?)\n"; + return 1; + } + + auto ret = g_pPluginManager->ensurePluginsLoadState(); + if (ret != LOADSTATE_OK) + return 1; + } else if (command[0] == "disable") { + if (command.size() < 2) { + std::cerr << Colors::RED << "✖" << Colors::RESET << " Not enough args for disable.\n"; + return 1; + } + + if (!g_pPluginManager->disablePlugin(command[1])) { + std::cerr << Colors::RED << "✖" << Colors::RESET << " Couldn't disable plugin (missing?)\n"; + return 1; + } + + auto ret = g_pPluginManager->ensurePluginsLoadState(); + if (ret != LOADSTATE_OK) + return 1; + } else if (command[0] == "reload") { + auto ret = g_pPluginManager->ensurePluginsLoadState(); + + if (ret != LOADSTATE_OK && notify) { + switch (ret) { + case LOADSTATE_FAIL: + case LOADSTATE_PARTIAL_FAIL: g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Failed to load plugins"); break; + case LOADSTATE_HEADERS_OUTDATED: + g_pPluginManager->notify(ICON_ERROR, 0, 10000, "[hyprpm] Failed to load plugins: Outdated headers. Please run hyprpm update manually."); + break; + default: break; + } + } else if (notify) { + g_pPluginManager->notify(ICON_OK, 0, 4000, "[hyprpm] Loaded plugins"); + } + } else if (command[0] == "list") { + g_pPluginManager->listAllPlugins(); + } else { + std::cout << HELP; + return 1; + } + + return 0; +} \ No newline at end of file diff --git a/hyprpm/src/meson.build b/hyprpm/src/meson.build new file mode 100644 index 00000000..0adae7aa --- /dev/null +++ b/hyprpm/src/meson.build @@ -0,0 +1,10 @@ +globber = run_command('sh', '-c', 'find . -name "*.cpp" | sort', check: true) +src = globber.stdout().strip().split('\n') + +executable('hyprpm', src, + dependencies: [ + dependency('threads'), + dependency('tomlplusplus') + ], + install : true +) diff --git a/hyprpm/src/progress/CProgressBar.cpp b/hyprpm/src/progress/CProgressBar.cpp new file mode 100644 index 00000000..69f51dd2 --- /dev/null +++ b/hyprpm/src/progress/CProgressBar.cpp @@ -0,0 +1,80 @@ +#include "CProgressBar.hpp" + +#include +#include +#include +#include + +#include +#include +#include + +#include "../helpers/Colors.hpp" + +void CProgressBar::printMessageAbove(const std::string& msg) { + struct winsize w; + ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); + + std::string spaces; + for (size_t i = 0; i < w.ws_col; ++i) { + spaces += ' '; + } + + std::cout << "\r" << spaces << "\r" << msg << "\n"; + print(); +} + +void CProgressBar::print() { + struct winsize w; + ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); + + if (m_bFirstPrint) + std::cout << "\n"; + m_bFirstPrint = false; + + std::string spaces; + for (size_t i = 0; i < w.ws_col; ++i) { + spaces += ' '; + } + + std::cout << "\r" << spaces << "\r"; + + std::string message = ""; + + float percentDone = 0; + if (m_fPercentage >= 0) + percentDone = m_fPercentage; + else + percentDone = (float)m_iSteps / (float)m_iMaxSteps; + + const auto BARWIDTH = std::clamp(w.ws_col - m_szCurrentMessage.length() - 2, 0UL, 50UL); + + // draw bar + message += std::string{" "} + Colors::GREEN; + size_t i = 0; + for (; i < std::floor(percentDone * BARWIDTH); ++i) { + message += "━"; + } + + if (i < BARWIDTH) { + i++; + + message += std::string{"╍"} + Colors::RESET; + + for (; i < BARWIDTH; ++i) { + message += "━"; + } + } else + message += Colors::RESET; + + // draw progress + if (m_fPercentage >= 0) + message += " " + std::format("{}%", static_cast(percentDone * 100.0)) + " "; + else + message += " " + std::format("{} / {}", m_iSteps, m_iMaxSteps) + " "; + + // draw message + std::cout << message + " " + m_szCurrentMessage; + + std::fflush(stdout); +} \ No newline at end of file diff --git a/hyprpm/src/progress/CProgressBar.hpp b/hyprpm/src/progress/CProgressBar.hpp new file mode 100644 index 00000000..6ac18f21 --- /dev/null +++ b/hyprpm/src/progress/CProgressBar.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include + +class CProgressBar { + public: + void print(); + void printMessageAbove(const std::string& msg); + + std::string m_szCurrentMessage = ""; + size_t m_iSteps = 0; + size_t m_iMaxSteps = 0; + float m_fPercentage = -1; // if != -1, use percentage + + private: + bool m_bFirstPrint = true; +}; \ No newline at end of file diff --git a/meson.build b/meson.build index de29528e..81d6e403 100644 --- a/meson.build +++ b/meson.build @@ -80,6 +80,7 @@ endforeach subdir('protocols') subdir('src') subdir('hyprctl') +subdir('hyprpm/src') subdir('assets') subdir('example') subdir('docs') diff --git a/nix/default.nix b/nix/default.nix index 7ddeae94..68b1bb22 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -20,6 +20,7 @@ pango, pciutils, systemd, + tomlplusplus, udis86, wayland, wayland-protocols, @@ -81,19 +82,20 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov buildInputs = [ - git cairo + git hyprland-protocols - libGL libdrm_2_4_118 + libGL libinput libxkbcommon mesa pango + pciutils + tomlplusplus udis86 wayland wayland-protocols - pciutils wlroots ] ++ lib.optionals enableXWayland [libxcb xcbutilwm xwayland] From a794eecd6a71e431b654cebb1b28dbff0d6da079 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 7 Dec 2023 10:46:12 +0000 Subject: [PATCH 349/513] README: add note about hyprpm + clang-format --- README.md | 1 + src/managers/KeybindManager.cpp | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 82dd0731..9f4aa847 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ easy IPC, much more QoL stuff than other wlr-based compositors and more... - Much more QoL stuff than other wlr-based compositors - Custom bezier curves for the best animations - Powerful plugin support +- Built-in plugin manager - Tearing support for better gaming performance - Easily expandable and readable codebase - Fast and active development diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 9bf05a35..2046b867 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -800,13 +800,13 @@ void CKeybindManager::changeworkspace(std::string args) { static auto* const PALLOWWORKSPACECYCLES = &g_pConfigManager->getConfigValuePtr("binds:allow_workspace_cycles")->intValue; static auto* const PWORKSPACECENTERON = &g_pConfigManager->getConfigValuePtr("binds:workspace_center_on")->intValue; - const auto PMONITOR = g_pCompositor->m_pLastMonitor; + const auto PMONITOR = g_pCompositor->m_pLastMonitor; if (!PMONITOR) return; - const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); - const bool EXPLICITPREVIOUS = args.starts_with("previous"); + const auto PCURRENTWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); + const bool EXPLICITPREVIOUS = args.starts_with("previous"); if (args.starts_with("previous")) { // Do nothing if there's no previous workspace, otherwise switch to it. From d9175a0181eb54b14e58b9ce655df3bc74e4ae8c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 7 Dec 2023 17:22:02 +0000 Subject: [PATCH 350/513] hyprpm: fix with system headers fixes #4082 --- hyprpm/src/core/PluginManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 8efcdf98..d3e6f171 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -253,7 +253,7 @@ eHeadersErrors CPluginManager::headersValid() { const auto HLVER = getHyprlandVersion(); // find headers commit - auto headers = execAndGet("pkg-config --cflags hyprland"); + auto headers = execAndGet("pkg-config --cflags --keep-system-cflags hyprland"); if (!headers.contains("-I/")) return HEADERS_MISSING; From aa020a2a1a560bd42f7ddc8c4808fd6db396ee8b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Thu, 7 Dec 2023 17:58:13 +0000 Subject: [PATCH 351/513] toplevel-export: commence render pass before reading fixes #4070 --- src/protocols/ToplevelExport.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 23ae996e..3c80eb18 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -394,14 +394,16 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times return false; } - g_pHyprOpenGL->m_RenderData.mainFB->bind(); + g_pHyprRenderer->endRender(); + + g_pHyprRenderer->makeEGLCurrent(); + + outFB.bind(); glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(0, 0, frame->box.width, frame->box.height, PFORMAT->glFormat, PFORMAT->glType, data); - g_pHyprRenderer->endRender(); - wlr_buffer_end_data_ptr_access(frame->buffer); if (frame->overlayCursor) From 004bf94a23223265c96e348a84d1d044a009c566 Mon Sep 17 00:00:00 2001 From: dranull <150595692+dranull@users.noreply.github.com> Date: Thu, 7 Dec 2023 22:12:08 +0000 Subject: [PATCH 352/513] keybinds: Keep focus on special when switching workspaces (#4084) --- src/helpers/Monitor.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index c1ae3503..c112d07d 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -533,24 +533,24 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool } } - static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; + if (!g_pCompositor->m_pLastMonitor->specialWorkspaceID) { + static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; + CWindow* pWindow = pWorkspace->getLastFocusedWindow(); - if (const auto PLASTWINDOW = pWorkspace->getLastFocusedWindow(); PLASTWINDOW) - g_pCompositor->focusWindow(PLASTWINDOW); - else { - CWindow* pWindow = nullptr; + if (!pWindow) { + if (*PFOLLOWMOUSE == 1) + pWindow = g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal()); - if (*PFOLLOWMOUSE == 1) - pWindow = g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal()); + if (!pWindow) + pWindow = g_pCompositor->getTopLeftWindowOnWorkspace(pWorkspace->m_iID); - if (!pWindow) - pWindow = g_pCompositor->getTopLeftWindowOnWorkspace(pWorkspace->m_iID); - - if (!pWindow) - pWindow = g_pCompositor->getFirstWindowOnWorkspace(pWorkspace->m_iID); + if (!pWindow) + pWindow = g_pCompositor->getFirstWindowOnWorkspace(pWorkspace->m_iID); + } g_pCompositor->focusWindow(pWindow); } + if (!noMouseMove) g_pInputManager->simulateMouseMovement(); From 6fb1b89b982eea26ecae75b93f1742537c4f31ae Mon Sep 17 00:00:00 2001 From: thejch <66577496+thejch@users.noreply.github.com> Date: Thu, 7 Dec 2023 14:36:18 -0800 Subject: [PATCH 353/513] makefile: add rm hyprpm for uninstall (#4086) --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index f03931fe..9e9d7afc 100644 --- a/Makefile +++ b/Makefile @@ -60,6 +60,7 @@ uninstall: rm -f ${PREFIX}/share/wayland-sessions/hyprland.desktop rm -f ${PREFIX}/bin/Hyprland rm -f ${PREFIX}/bin/hyprctl + rm -f ${PREFIX}/bin/hyprpm rm -f ${PREFIX}/lib/libwlroots.so.13032 rm -rf ${PREFIX}/share/hyprland rm -f ${PREFIX}/share/man/man1/Hyprland.1 From 288f1863f0b6886e0cdf85d16bb2460bb042acf2 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 8 Dec 2023 15:40:01 +0000 Subject: [PATCH 354/513] hyprctl: allow instances without HIS --- hyprctl/main.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index a53c4c3f..2f0e08ed 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -330,6 +330,12 @@ int main(int argc, char** argv) { fullRequest = fullArgs + "/" + fullRequest; + // instances is HIS-independent + if (fullRequest.contains("/instances")) { + instancesRequest(json); + return 0; + } + if (overrideInstance.contains("_")) instanceSignature = overrideInstance; else if (!overrideInstance.empty()) { @@ -399,8 +405,6 @@ int main(int argc, char** argv) { request(fullRequest); else if (fullRequest.contains("/rollinglog")) request(fullRequest); - else if (fullRequest.contains("/instances")) - instancesRequest(json); else if (fullRequest.contains("/switchxkblayout")) request(fullRequest, 2); else if (fullRequest.contains("/seterror")) From 11d1c50420cdeaa5426b837a6479455f47368f29 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 8 Dec 2023 16:02:16 +0000 Subject: [PATCH 355/513] windowrules: add focus param --- src/Compositor.cpp | 4 ++++ src/Window.hpp | 1 + src/config/ConfigManager.cpp | 18 ++++++++++++++++-- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 98f51204..f3d048a9 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -943,6 +943,8 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) { // we need to make the PLASTWINDOW not equal to m_pLastWindow so that RENDERDATA is correct for an unfocused window if (windowValidMapped(PLASTWINDOW)) { + PLASTWINDOW->updateDynamicRules(); + updateWindowAnimatedDecorationValues(PLASTWINDOW); if (!pWindow->m_bIsX11 || pWindow->m_iX11Type == 1) @@ -960,6 +962,8 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) { g_pXWaylandManager->activateWindow(pWindow, true); // sets the m_pLastWindow + pWindow->updateDynamicRules(); + updateWindowAnimatedDecorationValues(pWindow); if (pWindow->m_bIsUrgent) diff --git a/src/Window.hpp b/src/Window.hpp index f9873ead..810400d7 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -155,6 +155,7 @@ struct SWindowRule { int bFloating = -1; int bFullscreen = -1; int bPinned = -1; + int bFocus = -1; std::string szWorkspace = ""; // empty means any }; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 41248d08..91fa0eb9 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1028,9 +1028,10 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s const auto FULLSCREENPOS = VALUE.find("fullscreen:"); const auto PINNEDPOS = VALUE.find("pinned:"); const auto WORKSPACEPOS = VALUE.find("workspace:"); + const auto FOCUSPOS = VALUE.find("focus:"); if (TITLEPOS == std::string::npos && CLASSPOS == std::string::npos && X11POS == std::string::npos && FLOATPOS == std::string::npos && FULLSCREENPOS == std::string::npos && - PINNEDPOS == std::string::npos && WORKSPACEPOS == std::string::npos) { + PINNEDPOS == std::string::npos && WORKSPACEPOS == std::string::npos && FOCUSPOS == std::string::npos) { Debug::log(ERR, "Invalid rulev2 syntax: {}", VALUE); parseError = "Invalid rulev2 syntax: " + VALUE; return; @@ -1054,7 +1055,9 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s if (PINNEDPOS > pos && PINNEDPOS < min) min = PINNEDPOS; if (WORKSPACEPOS > pos && WORKSPACEPOS < min) - min = PINNEDPOS; + min = WORKSPACEPOS; + if (FOCUSPOS > pos && FOCUSPOS < min) + min = FOCUSPOS; result = result.substr(0, min - pos); @@ -1087,6 +1090,9 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s if (WORKSPACEPOS != std::string::npos) rule.szWorkspace = extract(WORKSPACEPOS + 10); + if (FOCUSPOS != std::string::npos) + rule.bFocus = extract(FOCUSPOS + 6) == "1" ? 1 : 0; + if (RULE == "unset") { std::erase_if(m_dWindowRules, [&](const SWindowRule& other) { if (!other.v2) { @@ -1113,6 +1119,9 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s if (!rule.szWorkspace.empty() && rule.szWorkspace != other.szWorkspace) return false; + if (rule.bFocus != -1 && rule.bFocus != other.bFocus) + return false; + return true; } }); @@ -1965,6 +1974,11 @@ std::vector CConfigManager::getMatchingRules(CWindow* pWindow) { continue; } + if (rule.bFocus != -1) { + if (rule.bFocus != (g_pCompositor->m_pLastWindow == pWindow)) + continue; + } + if (!rule.szWorkspace.empty()) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); From dd0714c22a7f588c1c80f83b45f66f034f83a884 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Dec 2023 04:07:28 +0000 Subject: [PATCH 356/513] input: add relative_input for tablets closes #2639 --- src/config/ConfigManager.cpp | 2 ++ src/helpers/WLClasses.hpp | 2 ++ src/managers/input/InputManager.cpp | 5 ++++- src/managers/input/Tablets.cpp | 13 ++++++++++--- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 91fa0eb9..28f3b746 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -250,6 +250,7 @@ void CConfigManager::setDefaultVars() { configValues["input:tablet:output"].strValue = STRVAL_EMPTY; configValues["input:tablet:region_position"].vecValue = Vector2D(); configValues["input:tablet:region_size"].vecValue = Vector2D(); + configValues["input:tablet:relative_input"].intValue = 0; configValues["binds:pass_mouse_when_bound"].intValue = 0; configValues["binds:scroll_event_delay"].intValue = 300; @@ -310,6 +311,7 @@ void CConfigManager::setDeviceDefaultVars(const std::string& dev) { cfgValues["enabled"].intValue = 1; // only for mice / touchpads cfgValues["region_position"].vecValue = Vector2D(); // only for tablets cfgValues["region_size"].vecValue = Vector2D(); // only for tablets + cfgValues["relative_input"].intValue = 0; // only for tablets } void CConfigManager::setDefaultAnimationVars() { diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index d381fa0d..644a6bdb 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -252,6 +252,8 @@ struct STablet { wlr_tablet_v2_tablet* wlrTabletV2 = nullptr; wlr_input_device* wlrDevice = nullptr; + bool relativeInput = false; + std::string name = ""; // diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 9ef1b4a3..21c9435d 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1494,7 +1494,10 @@ void CInputManager::setTabletConfigs() { if (wlr_input_device_is_libinput(t.wlrDevice)) { const auto LIBINPUTDEV = (libinput_device*)wlr_libinput_get_device_handle(t.wlrDevice); - const int ROTATION = std::clamp(g_pConfigManager->getDeviceInt(t.name, "transform", "input:tablet:transform"), 0, 7); + const auto RELINPUT = g_pConfigManager->getDeviceInt(t.name, "relative_input", "input:tablet:relative_input"); + t.relativeInput = RELINPUT; + + const int ROTATION = std::clamp(g_pConfigManager->getDeviceInt(t.name, "transform", "input:tablet:transform"), 0, 7); Debug::log(LOG, "Setting calibration matrix for device {}", t.name); libinput_device_config_calibration_set_matrix(LIBINPUTDEV, MATRICES[ROTATION]); diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index e5968a5a..2c1681c1 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -43,9 +43,16 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) { g_pInputManager->m_tmrLastCursorMovement.reset(); break; default: - double x = (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_X) ? EVENT->x : NAN; - double y = (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_Y) ? EVENT->y : NAN; - wlr_cursor_warp_absolute(g_pCompositor->m_sWLRCursor, PTAB->wlrDevice, x, y); + double x = (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_X) ? EVENT->x : NAN; + double dx = (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_X) ? EVENT->dx : NAN; + double y = (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_Y) ? EVENT->y : NAN; + double dy = (EVENT->updated_axes & WLR_TABLET_TOOL_AXIS_Y) ? EVENT->dy : NAN; + + if (PTAB->relativeInput) + wlr_cursor_move(g_pCompositor->m_sWLRCursor, PTAB->wlrDevice, dx, dy); + else + wlr_cursor_warp_absolute(g_pCompositor->m_sWLRCursor, PTAB->wlrDevice, x, y); + g_pInputManager->refocus(); g_pInputManager->m_tmrLastCursorMovement.reset(); break; From 9132660768668e1e14d95b8e8b3b02c4b000f137 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Dec 2023 16:16:46 +0000 Subject: [PATCH 357/513] functionHooks: fix incorrect protlen calcs --- src/plugins/HookSystem.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/plugins/HookSystem.cpp b/src/plugins/HookSystem.cpp index d7a366f3..04b12134 100644 --- a/src/plugins/HookSystem.cpp +++ b/src/plugins/HookSystem.cpp @@ -128,8 +128,11 @@ bool CFunctionHook::hook() { (uint64_t)((uint8_t*)m_pSource + sizeof(ABSOLUTE_JMP_ADDRESS)); // make jump to hk - mprotect((uint8_t*)m_pSource - ((uint64_t)m_pSource) % sysconf(_SC_PAGE_SIZE), sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE | PROT_EXEC); - memcpy(m_pSource, ABSOLUTE_JMP_ADDRESS, sizeof(ABSOLUTE_JMP_ADDRESS)); + const auto PAGESIZE = sysconf(_SC_PAGE_SIZE); + const uint8_t* PROTSTART = (uint8_t*)m_pSource - ((uint64_t)m_pSource % PAGESIZE); + const size_t PROTLEN = std::ceil((float)(HOOKSIZE + ((uint64_t)m_pSource - (uint64_t)PROTSTART)) / (float)PAGESIZE) * PAGESIZE; + mprotect((uint8_t*)PROTSTART, PROTLEN, PROT_READ | PROT_WRITE | PROT_EXEC); + memcpy((uint8_t*)m_pSource, ABSOLUTE_JMP_ADDRESS, sizeof(ABSOLUTE_JMP_ADDRESS)); // make popq %rax and NOP all remaining memcpy((uint8_t*)m_pSource + sizeof(ABSOLUTE_JMP_ADDRESS), POP_RAX, sizeof(POP_RAX)); @@ -140,7 +143,7 @@ bool CFunctionHook::hook() { *(uint64_t*)((uint8_t*)m_pSource + ABSOLUTE_JMP_ADDRESS_OFFSET) = (uint64_t)(m_pDestination); // revert mprot - mprotect((uint8_t*)m_pSource - ((uint64_t)m_pSource) % sysconf(_SC_PAGE_SIZE), sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_EXEC); + mprotect((uint8_t*)PROTSTART, PROTLEN, PROT_READ | PROT_EXEC); // set original addr to trampo addr m_pOriginal = m_pTrampolineAddr; From 89d8f665b5c661a4b373f766692b3d68c3cd294f Mon Sep 17 00:00:00 2001 From: dranull <150595692+dranull@users.noreply.github.com> Date: Sat, 9 Dec 2023 18:27:30 +0000 Subject: [PATCH 358/513] config: Avoid regenerating config if --config is used (#4103) --- src/config/ConfigManager.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 28f3b746..71841804 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1610,10 +1610,16 @@ void CConfigManager::loadConfigLoadVars() { ifs.open(mainConfigPath); if (!ifs.good()) { - Debug::log(WARN, "Config reading error. Attempting to generate, backing up old one if exists"); - ifs.close(); + if (!g_pCompositor->explicitConfigPath.empty()) { + Debug::log(WARN, "Config reading error!"); + parseError = "Broken config file! (Could not read)"; + return; + } + + Debug::log(WARN, "Config reading error. Attempting to generate, backing up old one if exists"); + if (std::filesystem::exists(mainConfigPath)) std::filesystem::rename(mainConfigPath, mainConfigPath + ".backup"); From 0ebbf371ffdf5c1b1bfad549e24a47b0dfee508e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Dec 2023 18:38:32 +0000 Subject: [PATCH 359/513] renderer: improve fullscreen workspace client rendering fixes #4076 --- src/render/Renderer.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index d20e10b8..0821e0f0 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -168,7 +168,8 @@ bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, CMonitor* pMonitor, CWo if (PWINDOWWORKSPACE->m_vRenderOffset.isBeingAnimated() || PWINDOWWORKSPACE->m_fAlpha.isBeingAnimated() || PWINDOWWORKSPACE->m_bForceRendering) { return true; } else { - if (!(!PWINDOWWORKSPACE->m_bHasFullscreenWindow || pWindow->m_bIsFullscreen || (pWindow->m_bIsFloating && pWindow->m_bCreatedOverFullscreen))) + if (PWINDOWWORKSPACE->m_bHasFullscreenWindow && !pWindow->m_bIsFullscreen && !pWindow->m_bIsFloating && !pWindow->m_bCreatedOverFullscreen && + pWindow->m_fAlpha.fl() == 0) return false; } } @@ -220,7 +221,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, CWorksp // loop over the tiled windows that are fading out for (auto& w : g_pCompositor->m_vWindows) { - if (w->m_iWorkspaceID != pMonitor->activeWorkspace) + if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) continue; if (w->m_fAlpha.fl() == 0.f) @@ -237,7 +238,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, CWorksp // and floating ones too for (auto& w : g_pCompositor->m_vWindows) { - if (w->m_iWorkspaceID != pMonitor->activeWorkspace) + if (!shouldRenderWindow(w.get(), pMonitor, pWorkspace)) continue; if (w->m_fAlpha.fl() == 0.f) From af6aae4e12b96fff701d8ae8fcb48ea8bb51009f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sat, 9 Dec 2023 18:41:32 +0000 Subject: [PATCH 360/513] renderer: don't use clipBox for pinned window occlusion during animations ref #4094 --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 0821e0f0..08765849 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -462,7 +462,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* } // if window is floating and we have a slide animation, clip it to its full bb - if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bIsFullscreen && PWORKSPACE->m_vRenderOffset.isBeingAnimated()) { + if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bIsFullscreen && PWORKSPACE->m_vRenderOffset.isBeingAnimated() && !pWindow->m_bPinned) { CRegion rg = pWindow->getFullWindowBoundingBox().translate(-pMonitor->vecPosition + PWORKSPACE->m_vRenderOffset.vec()).scale(pMonitor->scale); g_pHyprOpenGL->m_RenderData.clipBox = rg.getExtents(); } From b3dc58e1047cba0778831bdb069c3ceba6ec216e Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 10 Dec 2023 16:18:30 +0000 Subject: [PATCH 361/513] hyprpm: clone plugins recursively --- hyprpm/src/core/PluginManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index d3e6f171..e6e0a750 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -105,7 +105,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url) { progress.printMessageAbove(std::string{Colors::RESET} + " → Cloning " + url); - std::string ret = execAndGet("cd /tmp/hyprpm && git clone " + url + " new"); + std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + url + " new"); if (!std::filesystem::exists("/tmp/hyprpm/new")) { std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Could not clone the plugin repository. shell returned:\n" << ret << "\n"; @@ -438,7 +438,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { progress.printMessageAbove(std::string{Colors::RESET} + " → Cloning " + repo.url); - std::string ret = execAndGet("cd /tmp/hyprpm && git clone " + repo.url + " update"); + std::string ret = execAndGet("cd /tmp/hyprpm && git clone --recursive " + repo.url + " update"); if (!std::filesystem::exists("/tmp/hyprpm/update")) { std::cout << "\n" << std::string{Colors::RED} + "✖" + Colors::RESET + " could not clone repo: shell returned:\n" + ret; From 9f5b9053c6fb7942a0ff27dc61fc6874e4354888 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sun, 10 Dec 2023 16:28:12 +0000 Subject: [PATCH 362/513] internal: Remake borders as window decorations (#4104) --- src/Window.cpp | 4 +- src/config/ConfigManager.cpp | 1 + src/events/Windows.cpp | 21 ++-- src/layout/DwindleLayout.cpp | 16 ++- src/layout/MasterLayout.cpp | 16 ++- src/managers/AnimationManager.cpp | 2 + src/render/Renderer.cpp | 35 +----- .../decorations/CHyprBorderDecoration.cpp | 101 ++++++++++++++++++ .../decorations/CHyprBorderDecoration.hpp | 39 +++++++ .../decorations/CHyprDropShadowDecoration.cpp | 10 +- .../decorations/DecorationPositioner.cpp | 33 +++--- .../decorations/IHyprWindowDecoration.hpp | 1 + 12 files changed, 201 insertions(+), 78 deletions(-) create mode 100644 src/render/decorations/CHyprBorderDecoration.cpp create mode 100644 src/render/decorations/CHyprBorderDecoration.hpp diff --git a/src/Window.cpp b/src/Window.cpp index 789882de..58ec5c72 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -2,6 +2,7 @@ #include "Compositor.hpp" #include "render/decorations/CHyprDropShadowDecoration.hpp" #include "render/decorations/CHyprGroupBarDecoration.hpp" +#include "render/decorations/CHyprBorderDecoration.hpp" CWindow::CWindow() { m_vRealPosition.create(AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), (void*)this, AVARDAMAGE_ENTIRE); @@ -14,6 +15,7 @@ CWindow::CWindow() { m_fDimPercent.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeDim"), (void*)this, AVARDAMAGE_ENTIRE); addWindowDeco(std::make_unique(this)); + addWindowDeco(std::make_unique(this)); } CWindow::~CWindow() { @@ -964,7 +966,7 @@ float CWindow::rounding() { float rounding = m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? *PROUNDING : m_sAdditionalConfigData.rounding.toUnderlying(); - return rounding; + return m_sSpecialRenderData.rounding ? rounding : 0; } void CWindow::updateSpecialRenderData() { diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 71841804..e5eb4cdb 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -80,6 +80,7 @@ void CConfigManager::setDefaultVars() { configValues["general:apply_sens_to_raw"].intValue = 0; configValues["general:border_size"].intValue = 1; configValues["general:no_border_on_floating"].intValue = 0; + configValues["general:border_part_of_window"].intValue = 1; configValues["general:gaps_in"].intValue = 5; configValues["general:gaps_out"].intValue = 20; configValues["general:gaps_workspaces"].intValue = 0; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 2ee70264..ff68d13f 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -506,14 +506,6 @@ void Events::listener_mapWindow(void* owner, void* data) { "XWayland Window Late"); } - // do the animation thing - g_pAnimationManager->onWindowPostCreateClose(PWINDOW, false); - PWINDOW->m_fAlpha.setValueAndWarp(0.f); - PWINDOW->m_fAlpha = 1.f; - - PWINDOW->m_vRealPosition.setCallbackOnEnd(setAnimToMove); - PWINDOW->m_vRealSize.setCallbackOnEnd(setAnimToMove); - if ((requestsFullscreen && (!PWINDOW->m_bNoFullscreenRequest || overridingNoFullscreen)) || (requestsMaximize && (!PWINDOW->m_bNoMaximizeRequest || overridingNoMaximize)) || requestsFakeFullscreen) { // fix fullscreen on requested (basically do a switcheroo) @@ -627,6 +619,19 @@ void Events::listener_mapWindow(void* owner, void* data) { g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", std::format("{:x},{},{},{}", PWINDOW, workspaceID, g_pXWaylandManager->getAppIDClass(PWINDOW), PWINDOW->m_szTitle)}); EMIT_HOOK_EVENT("openWindow", PWINDOW); + // apply data from default decos. Borders, shadows. + g_pDecorationPositioner->forceRecalcFor(PWINDOW); + PWINDOW->updateWindowDecos(); + g_pLayoutManager->getCurrentLayout()->recalculateWindow(PWINDOW); + + // do animations + g_pAnimationManager->onWindowPostCreateClose(PWINDOW, false); + PWINDOW->m_fAlpha.setValueAndWarp(0.f); + PWINDOW->m_fAlpha = 1.f; + + PWINDOW->m_vRealPosition.setCallbackOnEnd(setAnimToMove); + PWINDOW->m_vRealSize.setCallbackOnEnd(setAnimToMove); + // recalc the values for this window g_pCompositor->updateWindowAnimatedDecorationValues(PWINDOW); // avoid this window being visible diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index a01c3b8c..c1009a47 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -149,24 +149,20 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for PWINDOW->m_sSpecialRenderData.rounding = false; PWINDOW->m_sSpecialRenderData.shadow = false; + PWINDOW->updateWindowDecos(); + const auto RESERVED = PWINDOW->getFullWindowReservedArea(); - const int BORDERSIZE = PWINDOW->getRealBorderSize(); - - PWINDOW->m_vRealPosition = PWINDOW->m_vPosition + Vector2D(BORDERSIZE, BORDERSIZE) + RESERVED.topLeft; - PWINDOW->m_vRealSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE) - (RESERVED.topLeft + RESERVED.bottomRight); - - PWINDOW->updateWindowDecos(); + PWINDOW->m_vRealPosition = PWINDOW->m_vPosition + RESERVED.topLeft; + PWINDOW->m_vRealSize = PWINDOW->m_vSize - (RESERVED.topLeft + RESERVED.bottomRight); g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv()); return; } - const int BORDERSIZE = PWINDOW->getRealBorderSize(); - - auto calcPos = PWINDOW->m_vPosition + Vector2D(BORDERSIZE, BORDERSIZE); - auto calcSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE); + auto calcPos = PWINDOW->m_vPosition; + auto calcSize = PWINDOW->m_vSize; const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut : gapsIn, DISPLAYTOP ? gapsOut : gapsIn); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 3977d8f6..8b12d669 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -667,24 +667,20 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { PWINDOW->m_sSpecialRenderData.rounding = false; PWINDOW->m_sSpecialRenderData.shadow = false; + PWINDOW->updateWindowDecos(); + const auto RESERVED = PWINDOW->getFullWindowReservedArea(); - const int BORDERSIZE = PWINDOW->getRealBorderSize(); - - PWINDOW->m_vRealPosition = PWINDOW->m_vPosition + Vector2D(BORDERSIZE, BORDERSIZE) + RESERVED.topLeft; - PWINDOW->m_vRealSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE) - (RESERVED.topLeft + RESERVED.bottomRight); - - PWINDOW->updateWindowDecos(); + PWINDOW->m_vRealPosition = PWINDOW->m_vPosition + RESERVED.topLeft; + PWINDOW->m_vRealSize = PWINDOW->m_vSize - (RESERVED.topLeft + RESERVED.bottomRight); g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goalv()); return; } - const int BORDERSIZE = PWINDOW->getRealBorderSize(); - - auto calcPos = PWINDOW->m_vPosition + Vector2D(BORDERSIZE, BORDERSIZE); - auto calcSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE); + auto calcPos = PWINDOW->m_vPosition; + auto calcSize = PWINDOW->m_vSize; const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut : gapsIn, DISPLAYTOP ? gapsOut : gapsIn); diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 3d6ebdd8..120e6f49 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -229,6 +229,8 @@ void CAnimationManager::tick() { case AVARDAMAGE_BORDER: { RASSERT(PWINDOW, "Tried to AVARDAMAGE_BORDER a non-window AVAR!"); + // TODO: move this to the border class + // damage only the border. static auto* const PROUNDING = &g_pConfigManager->getConfigValuePtr("decoration:rounding")->intValue; const auto ROUNDINGSIZE = *PROUNDING + 1; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 08765849..6731dff5 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -381,11 +381,10 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* TRACY_GPU_ZONE("RenderWindow"); - const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); - const auto REALPOS = pWindow->m_vRealPosition.vec() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset.vec()); - static auto* const PDIMAROUND = &g_pConfigManager->getConfigValuePtr("decoration:dim_around")->floatValue; - static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; - static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue; + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); + const auto REALPOS = pWindow->m_vRealPosition.vec() + (pWindow->m_bPinned ? Vector2D{} : PWORKSPACE->m_vRenderOffset.vec()); + static auto* const PDIMAROUND = &g_pConfigManager->getConfigValuePtr("decoration:dim_around")->floatValue; + static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue; SRenderData renderdata = {pMonitor, time}; CBox textureBox = {REALPOS.x, REALPOS.y, std::max(pWindow->m_vRealSize.vec().x, 5.0), std::max(pWindow->m_vRealSize.vec().y, 5.0)}; @@ -512,32 +511,6 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false; - if (renderdata.decorate && pWindow->m_sSpecialRenderData.border) { - auto grad = g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColor; - const bool ANIMATED = g_pHyprOpenGL->m_pCurrentWindow->m_fBorderFadeAnimationProgress.isBeingAnimated(); - float a1 = renderdata.fadeAlpha * renderdata.alpha * (ANIMATED ? g_pHyprOpenGL->m_pCurrentWindow->m_fBorderFadeAnimationProgress.fl() : 1.f); - - if (g_pHyprOpenGL->m_pCurrentWindow->m_fBorderAngleAnimationProgress.getConfig()->pValues->internalEnabled) { - grad.m_fAngle += g_pHyprOpenGL->m_pCurrentWindow->m_fBorderAngleAnimationProgress.fl() * M_PI * 2; - grad.m_fAngle = normalizeAngleRad(grad.m_fAngle); - } - - CBox windowBox = {renderdata.x - pMonitor->vecPosition.x, renderdata.y - pMonitor->vecPosition.y, renderdata.w, renderdata.h}; - - windowBox.scale(pMonitor->scale).round(); - - int borderSize = pWindow->m_sSpecialRenderData.borderSize.toUnderlying() == -1 ? *PBORDERSIZE : pWindow->m_sSpecialRenderData.borderSize.toUnderlying(); - if (pWindow->m_sAdditionalConfigData.borderSize.toUnderlying() != -1) - borderSize = pWindow->m_sAdditionalConfigData.borderSize.toUnderlying(); - - g_pHyprOpenGL->renderBorder(&windowBox, grad, renderdata.rounding, borderSize, a1); - - if (ANIMATED) { - float a2 = renderdata.fadeAlpha * renderdata.alpha * (1.f - g_pHyprOpenGL->m_pCurrentWindow->m_fBorderFadeAnimationProgress.fl()); - g_pHyprOpenGL->renderBorder(&windowBox, g_pHyprOpenGL->m_pCurrentWindow->m_cRealBorderColorPrevious, renderdata.rounding, borderSize, a2); - } - } - for (auto& wd : pWindow->m_dWindowDecorations) { if (wd->getDecorationLayer() != DECORATION_LAYER_OVER) continue; diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp new file mode 100644 index 00000000..560eb8ca --- /dev/null +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -0,0 +1,101 @@ +#include "CHyprBorderDecoration.hpp" +#include "../../Compositor.hpp" + +CHyprBorderDecoration::CHyprBorderDecoration(CWindow* pWindow) : IHyprWindowDecoration(pWindow) { + m_pWindow = pWindow; +} + +CHyprBorderDecoration::~CHyprBorderDecoration() { + ; +} + +SDecorationPositioningInfo CHyprBorderDecoration::getPositioningInfo() { + const auto BORDERSIZE = m_pWindow->getRealBorderSize(); + m_seExtents = {{BORDERSIZE, BORDERSIZE}, {BORDERSIZE, BORDERSIZE}}; + + if (doesntWantBorders()) + m_seExtents = {{}, {}}; + + SDecorationPositioningInfo info; + info.priority = 10000; + info.policy = DECORATION_POSITION_STICKY; + info.desiredExtents = m_seExtents; + info.reserved = true; + info.edges = DECORATION_EDGE_BOTTOM | DECORATION_EDGE_LEFT | DECORATION_EDGE_RIGHT | DECORATION_EDGE_TOP; + + m_seReportedExtents = m_seExtents; + return info; +} + +void CHyprBorderDecoration::onPositioningReply(const SDecorationPositioningReply& reply) { + m_bAssignedGeometry = reply.assignedGeometry; +} + +CBox CHyprBorderDecoration::assignedBoxGlobal() { + CBox box = m_bAssignedGeometry; + box.translate(g_pDecorationPositioner->getEdgeDefinedPoint(DECORATION_EDGE_BOTTOM | DECORATION_EDGE_LEFT | DECORATION_EDGE_RIGHT | DECORATION_EDGE_TOP, m_pWindow)); + + const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_pWindow->m_iWorkspaceID); + + if (!PWORKSPACE) + return box; + + const auto WORKSPACEOFFSET = PWORKSPACE && !m_pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D(); + return box.translate(WORKSPACEOFFSET); +} + +void CHyprBorderDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& offset) { + if (doesntWantBorders()) + return; + + if (m_bAssignedGeometry.width < m_seExtents.topLeft.x + 1 || m_bAssignedGeometry.height < m_seExtents.topLeft.y + 1) + return; + + auto grad = m_pWindow->m_cRealBorderColor; + const bool ANIMATED = m_pWindow->m_fBorderFadeAnimationProgress.isBeingAnimated(); + float a1 = a * (ANIMATED ? m_pWindow->m_fBorderFadeAnimationProgress.fl() : 1.f); + + if (m_pWindow->m_fBorderAngleAnimationProgress.getConfig()->pValues->internalEnabled) { + grad.m_fAngle += m_pWindow->m_fBorderAngleAnimationProgress.fl() * M_PI * 2; + grad.m_fAngle = normalizeAngleRad(grad.m_fAngle); + } + + CBox windowBox = assignedBoxGlobal().translate(-pMonitor->vecPosition).expand(-m_pWindow->getRealBorderSize()).scale(pMonitor->scale).round(); + + int borderSize = m_pWindow->getRealBorderSize(); + const auto ROUNDING = m_pWindow->rounding() * pMonitor->scale; + + g_pHyprOpenGL->renderBorder(&windowBox, grad, ROUNDING, borderSize, a1); + + if (ANIMATED) { + float a2 = a * (1.f - m_pWindow->m_fBorderFadeAnimationProgress.fl()); + g_pHyprOpenGL->renderBorder(&windowBox, m_pWindow->m_cRealBorderColorPrevious, ROUNDING, borderSize, a2); + } +} + +eDecorationType CHyprBorderDecoration::getDecorationType() { + return DECORATION_BORDER; +} + +void CHyprBorderDecoration::updateWindow(CWindow*) { + if (m_pWindow->getRealBorderSize() != m_seExtents.topLeft.x) + g_pDecorationPositioner->repositionDeco(this); +} + +void CHyprBorderDecoration::damageEntire() { + ; // ignored, done in animationManager. todo, move. +} + +eDecorationLayer CHyprBorderDecoration::getDecorationLayer() { + return DECORATION_LAYER_OVER; +} + +uint64_t CHyprBorderDecoration::getDecorationFlags() { + static auto* const PPARTOFWINDOW = &g_pConfigManager->getConfigValuePtr("general:border_part_of_window")->intValue; + + return *PPARTOFWINDOW && !doesntWantBorders() ? DECORATION_PART_OF_MAIN_WINDOW : 0; +} + +bool CHyprBorderDecoration::doesntWantBorders() { + return !m_pWindow->m_sSpecialRenderData.border || m_pWindow->m_bX11DoesntWantBorders; +} \ No newline at end of file diff --git a/src/render/decorations/CHyprBorderDecoration.hpp b/src/render/decorations/CHyprBorderDecoration.hpp new file mode 100644 index 00000000..770d1291 --- /dev/null +++ b/src/render/decorations/CHyprBorderDecoration.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include "IHyprWindowDecoration.hpp" + +class CHyprBorderDecoration : public IHyprWindowDecoration { + public: + CHyprBorderDecoration(CWindow*); + virtual ~CHyprBorderDecoration(); + + virtual SDecorationPositioningInfo getPositioningInfo(); + + virtual void onPositioningReply(const SDecorationPositioningReply& reply); + + virtual void draw(CMonitor*, float a, const Vector2D& offset); + + virtual eDecorationType getDecorationType(); + + virtual void updateWindow(CWindow*); + + virtual void damageEntire(); + + virtual eDecorationLayer getDecorationLayer(); + + virtual uint64_t getDecorationFlags(); + + private: + SWindowDecorationExtents m_seExtents; + SWindowDecorationExtents m_seReportedExtents; + + CWindow* m_pWindow = nullptr; + + Vector2D m_vLastWindowPos; + Vector2D m_vLastWindowSize; + + CBox m_bAssignedGeometry = {0}; + + CBox assignedBoxGlobal(); + bool doesntWantBorders(); +}; \ No newline at end of file diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index bbf6def4..5e70b639 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -116,13 +116,13 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D CBox withDecos = m_bLastWindowBoxWithDecos; // get window box - windowBox.translate(-pMonitor->vecPosition + WORKSPACEOFFSET).scale(pMonitor->scale).round(); - withDecos.translate(-pMonitor->vecPosition + WORKSPACEOFFSET).scale(pMonitor->scale).round(); + windowBox.translate(-pMonitor->vecPosition + WORKSPACEOFFSET); + withDecos.translate(-pMonitor->vecPosition + WORKSPACEOFFSET); - auto scaledDecoExtents = withDecos.extentsFrom(windowBox).round(); + auto extentss = withDecos.extentsFrom(windowBox); // add extents - windowBox.addExtents(scaledDecoExtents).round(); + windowBox.addExtents(extentss).scale(pMonitor->scale).round(); if (windowBox.width < 1 || windowBox.height < 1) return; // prevent assert failed @@ -159,7 +159,7 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D g_pHyprOpenGL->m_RenderData.damage = saveDamage; } else { - g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, a); + g_pHyprOpenGL->renderRoundedShadow(&fullBox, ROUNDING * pMonitor->scale, *PSHADOWSIZE * pMonitor->scale, m_pWindow->m_cRealShadowColor.col(), a); } if (m_seExtents != m_seReportedExtents) diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index b41b92a9..30e49ac1 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -21,14 +21,15 @@ Vector2D CDecorationPositioner::getEdgeDefinedPoint(uint32_t edges, CWindow* pWi const int EDGESNO = TOP + BOTTOM + LEFT + RIGHT; - if (EDGESNO == 0 || EDGESNO > 2) { + if (EDGESNO == 0 || EDGESNO == 3 || EDGESNO > 4) { Debug::log(ERR, "getEdgeDefinedPoint: invalid number of edges"); return {}; } - CBox wb = pWindow->getWindowMainSurfaceBox(); - const auto BORDERSIZE = pWindow->getRealBorderSize(); - wb.expand(BORDERSIZE); + CBox wb = pWindow->getWindowMainSurfaceBox(); + + if (EDGESNO == 4) + return wb.pos(); if (EDGESNO == 1) { if (TOP) @@ -137,9 +138,7 @@ void CDecorationPositioner::onWindowUpdate(CWindow* pWindow) { std::sort(datas.begin(), datas.end(), [](const auto& a, const auto& b) { return a->positioningInfo.priority > b->positioningInfo.priority; }); - CBox wb = pWindow->getWindowMainSurfaceBox(); - const auto BORDERSIZE = pWindow->getRealBorderSize(); - wb.expand(BORDERSIZE); + CBox wb = pWindow->getWindowMainSurfaceBox(); // calc reserved float reservedXL = 0, reservedYT = 0, reservedXR = 0, reservedYB = 0; @@ -199,7 +198,7 @@ void CDecorationPositioner::onWindowUpdate(CWindow* pWindow) { } if (wd->positioningInfo.policy == DECORATION_POSITION_STICKY) { - if (EDGESNO != 1) { + if (EDGESNO != 1 && EDGESNO != 4) { wd->lastReply = {}; wd->pDecoration->onPositioningReply({}); continue; @@ -219,7 +218,15 @@ void CDecorationPositioner::onWindowUpdate(CWindow* pWindow) { Vector2D pos, size; - if (LEFT) { + if (EDGESNO == 4) { + pos = wb.pos() - EDGEPOINT - Vector2D{stickyOffsetXL + desiredSize, stickyOffsetYT + desiredSize}; + size = wb.size() + Vector2D{stickyOffsetXL + stickyOffsetXR + desiredSize * 2, stickyOffsetYB + stickyOffsetYT + desiredSize * 2}; + + stickyOffsetXL += desiredSize; + stickyOffsetXR += desiredSize; + stickyOffsetYT += desiredSize; + stickyOffsetYB += desiredSize; + } else if (LEFT) { pos = wb.pos() - EDGEPOINT - Vector2D{stickyOffsetXL, 0}; pos.x -= desiredSize; size = {desiredSize, wb.size().y}; @@ -279,7 +286,7 @@ SWindowDecorationExtents CDecorationPositioner::getWindowDecorationReserved(CWin } SWindowDecorationExtents CDecorationPositioner::getWindowDecorationExtents(CWindow* pWindow, bool inputOnly) { - CBox accum = pWindow->getWindowMainSurfaceBox().expand(pWindow->getRealBorderSize()); + CBox accum = pWindow->getWindowMainSurfaceBox(); for (auto& data : m_vWindowPositioningDatas) { if (data->pWindow != pWindow) @@ -320,7 +327,7 @@ SWindowDecorationExtents CDecorationPositioner::getWindowDecorationExtents(CWind } CBox CDecorationPositioner::getBoxWithIncludedDecos(CWindow* pWindow) { - CBox accum = pWindow->getWindowMainSurfaceBox().expand(pWindow->getRealBorderSize()); + CBox accum = pWindow->getWindowMainSurfaceBox(); for (auto& data : m_vWindowPositioningDatas) { if (data->pWindow != pWindow) @@ -347,9 +354,9 @@ CBox CDecorationPositioner::getBoxWithIncludedDecos(CWindow* pWindow) { if (decoBox.y < accum.y) extentsToAdd.topLeft.y = accum.y - decoBox.y; if (decoBox.x + decoBox.w > accum.x + accum.w) - extentsToAdd.bottomRight.x = accum.x + accum.w - (decoBox.x + decoBox.w); + extentsToAdd.bottomRight.x = (decoBox.x + decoBox.w) - (accum.x + accum.w); if (decoBox.y + decoBox.h > accum.y + accum.h) - extentsToAdd.bottomRight.y = accum.y + accum.h - (decoBox.y + decoBox.h); + extentsToAdd.bottomRight.y = (decoBox.y + decoBox.h) - (accum.y + accum.h); accum.addExtents(extentsToAdd); } diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp index 15b00536..e0a34016 100644 --- a/src/render/decorations/IHyprWindowDecoration.hpp +++ b/src/render/decorations/IHyprWindowDecoration.hpp @@ -8,6 +8,7 @@ enum eDecorationType { DECORATION_NONE = -1, DECORATION_GROUPBAR, DECORATION_SHADOW, + DECORATION_BORDER, DECORATION_CUSTOM }; From 0c10b8ab2dad9851b00c0e99bb1fde3f01d5478c Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Sun, 10 Dec 2023 18:30:08 +0200 Subject: [PATCH 363/513] input: Add scroll_points option for device (#4101) --- src/config/ConfigManager.cpp | 2 ++ src/managers/input/InputManager.cpp | 31 ++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index e5eb4cdb..5eb26efc 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -236,6 +236,7 @@ void CConfigManager::setDefaultVars() { configValues["input:scroll_method"].strValue = STRVAL_EMPTY; configValues["input:scroll_button"].intValue = 0; configValues["input:scroll_button_lock"].intValue = 0; + configValues["input:scroll_points"].strValue = STRVAL_EMPTY; configValues["input:touchpad:natural_scroll"].intValue = 0; configValues["input:touchpad:disable_while_typing"].intValue = 1; configValues["input:touchpad:clickfinger_behavior"].intValue = 0; @@ -307,6 +308,7 @@ void CConfigManager::setDeviceDefaultVars(const std::string& dev) { cfgValues["scroll_method"].strValue = STRVAL_EMPTY; cfgValues["scroll_button"].intValue = 0; cfgValues["scroll_button_lock"].intValue = 0; + cfgValues["scroll_points"].strValue = STRVAL_EMPTY; cfgValues["transform"].intValue = 0; cfgValues["output"].strValue = STRVAL_EMPTY; cfgValues["enabled"].intValue = 1; // only for mice / touchpads diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 21c9435d..284b4da6 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -1066,23 +1066,40 @@ void CInputManager::setPointerConfigs() { libinput_device_config_accel_set_speed(LIBINPUTDEV, LIBINPUTSENS); const auto ACCELPROFILE = g_pConfigManager->getDeviceString(devname, "accel_profile", "input:accel_profile"); + const auto SCROLLPOINTS = g_pConfigManager->getDeviceString(devname, "scroll_points", "input:scroll_points"); - if (ACCELPROFILE == "") { + if (ACCELPROFILE.empty()) { libinput_device_config_accel_set_profile(LIBINPUTDEV, libinput_device_config_accel_get_default_profile(LIBINPUTDEV)); } else if (ACCELPROFILE == "adaptive") { libinput_device_config_accel_set_profile(LIBINPUTDEV, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE); } else if (ACCELPROFILE == "flat") { libinput_device_config_accel_set_profile(LIBINPUTDEV, LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT); } else if (ACCELPROFILE.starts_with("custom")) { - CVarList args = {ACCELPROFILE, 0, ' '}; + CVarList accelValues = {ACCELPROFILE, 0, ' '}; + try { - double step = std::stod(args[1]); - std::vector points; - for (size_t i = 2; i < args.size(); ++i) - points.push_back(std::stod(args[i])); + double accelStep = std::stod(accelValues[1]); + std::vector accelPoints; + for (size_t i = 2; i < accelValues.size(); ++i) { + accelPoints.push_back(std::stod(accelValues[i])); + } const auto CONFIG = libinput_config_accel_create(LIBINPUT_CONFIG_ACCEL_PROFILE_CUSTOM); - libinput_config_accel_set_points(CONFIG, LIBINPUT_ACCEL_TYPE_MOTION, step, points.size(), points.data()); + + if (!SCROLLPOINTS.empty()) { + CVarList scrollValues = {SCROLLPOINTS, 0, ' '}; + try { + double scrollStep = std::stod(scrollValues[0]); + std::vector scrollPoints; + for (size_t i = 1; i < scrollValues.size(); ++i) { + scrollPoints.push_back(std::stod(scrollValues[i])); + } + + libinput_config_accel_set_points(CONFIG, LIBINPUT_ACCEL_TYPE_SCROLL, scrollStep, scrollPoints.size(), scrollPoints.data()); + } catch (std::exception& e) { Debug::log(ERR, "Invalid values in scroll_points"); } + } + + libinput_config_accel_set_points(CONFIG, LIBINPUT_ACCEL_TYPE_MOTION, accelStep, accelPoints.size(), accelPoints.data()); libinput_device_config_accel_apply(LIBINPUTDEV, CONFIG); libinput_config_accel_destroy(CONFIG); } catch (std::exception& e) { Debug::log(ERR, "Invalid values in custom accel profile"); } From efdf07e295d00cf5391a8c0089967a69a76d9b08 Mon Sep 17 00:00:00 2001 From: nmzik Date: Sun, 10 Dec 2023 17:53:08 +0100 Subject: [PATCH 364/513] renderer: Allocate background texture only if required (#4111) --- src/render/OpenGL.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 845b3caa..da348a0f 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -1897,12 +1897,16 @@ void CHyprOpenGLImpl::renderSplash(cairo_t* const CAIRO, cairo_surface_t* const void CHyprOpenGLImpl::createBGTextureForMonitor(CMonitor* pMonitor) { RASSERT(m_RenderData.pMonitor, "Tried to createBGTex without begin()!"); + static auto* const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue; static auto* const PNOSPLASH = &g_pConfigManager->getConfigValuePtr("misc:disable_splash_rendering")->intValue; static auto* const PFORCEHYPRCHAN = &g_pConfigManager->getConfigValuePtr("misc:force_hypr_chan")->intValue; static auto* const PFORCEWALLPAPER = &g_pConfigManager->getConfigValuePtr("misc:force_default_wallpaper")->intValue; const auto FORCEWALLPAPER = std::clamp(*PFORCEWALLPAPER, static_cast(-1L), static_cast(2L)); + if (*PRENDERTEX) + return; + // release the last tex if exists const auto PTEX = &m_mMonitorBGTextures[pMonitor]; PTEX->destroyTexture(); From 359baa02147f0ff91c8c5156c5e83b6ec6976525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Conzelmann?= <45296195+zephvr@users.noreply.github.com> Date: Sun, 10 Dec 2023 20:26:25 +0100 Subject: [PATCH 365/513] ci: use composite action to minimize code duplication (#4112) --- .github/actions/setup_base/action.yml | 75 +++++++++++++++++ .github/workflows/ci.yaml | 113 +++++++++----------------- .github/workflows/security-checks.yml | 29 +++---- 3 files changed, 125 insertions(+), 92 deletions(-) create mode 100644 .github/actions/setup_base/action.yml diff --git a/.github/actions/setup_base/action.yml b/.github/actions/setup_base/action.yml new file mode 100644 index 00000000..2985ce9a --- /dev/null +++ b/.github/actions/setup_base/action.yml @@ -0,0 +1,75 @@ +name: "Setup base" + +inputs: + INSTALL_XORG_PKGS: + description: 'Install xorg dependencies' + required: false + default: false + +runs: + using: "composite" + steps: + - name: Get required pacman pkgs + shell: bash + run: | + sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf + pacman --noconfirm --noprogressbar -Syyu + pacman --noconfirm --noprogressbar -Sy \ + base-devel \ + cairo \ + clang \ + cmake \ + git \ + glm \ + glslang \ + go \ + jq \ + libc++ \ + libdisplay-info \ + libdrm \ + libepoxy \ + libfontenc \ + libglvnd \ + libinput \ + libliftoff \ + libxcvt \ + libxfont2 \ + libxkbcommon \ + libxkbfile \ + lld \ + meson \ + ninja \ + pango \ + pixman \ + pkgconf \ + scdoc \ + seatd \ + systemd \ + tomlplusplus \ + wayland \ + wayland-protocols \ + xcb-util-errors \ + xcb-util-renderutil \ + xcb-util-wm + + - name: Get Xorg pacman pkgs + shell: bash + if: inputs.INSTALL_XORG_PKGS == 'true' + run: | + pacman --noconfirm --noprogressbar -Sy \ + xorg-fonts-encodings \ + xorg-server-common \ + xorg-setxkbmap \ + xorg-xkbcomp \ + xorg-xwayland + + - name: Checkout Hyprland + uses: actions/checkout@v4 + with: + submodules: recursive + + # Fix an issue with actions/checkout where the checkout repo is not mark as safe + - name: Mark directory as safe for git + shell: bash + run: | + git config --global --add safe.directory /__w/Hyprland/Hyprland diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e68dc2a8..01bb43d1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -8,29 +8,20 @@ jobs: container: image: archlinux steps: - - name: Get required pacman pkgs - run: | - sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf - pacman --noconfirm --noprogressbar -Syyu - pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd python libliftoff tomlplusplus - - name: Set up user - run: | - useradd -m githubuser - echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers - - name: Install libdisplay-info from the AUR - run: | - su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar" - - name: Fix permissions for git - run: | - git config --global --add safe.directory /__w/Hyprland/Hyprland - - name: Checkout Hyprland - uses: actions/checkout@v3 + - name: Checkout repository actions + uses: actions/checkout@v4 with: - submodules: recursive + sparse-checkout: .github/actions + + - name: Setup base + uses: ./.github/actions/setup_base + with: + INSTALL_XORG_PKGS: true + - name: Build Hyprland run: | - git submodule sync --recursive && git submodule update --init --force --recursive make all + - name: Compress and package artifacts run: | mkdir x86_64-pc-linux-gnu @@ -45,6 +36,7 @@ jobs: cp -r example/ hyprland/ cp -r assets/ hyprland/ tar -cvf Hyprland.tar.xz hyprland + - name: Release uses: actions/upload-artifact@v3 with: @@ -57,28 +49,19 @@ jobs: container: image: archlinux steps: - - name: Download dependencies - run: | - sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf - pacman --noconfirm --noprogressbar -Syyu - pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd cmake jq python libliftoff tomlplusplus - - name: Set up user - run: | - useradd -m githubuser - echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers - - name: Install libdisplay-info from the AUR - run: | - su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar" - - name: Checkout Hyprland - uses: actions/checkout@v3 + - name: Checkout repository actions + uses: actions/checkout@v4 with: - submodules: true + sparse-checkout: .github/actions + + - name: Setup base + uses: ./.github/actions/setup_base + - name: Configure - run: | - meson obj-x86_64-pc-linux-gnu \ - -Ddefault_library=static + run: meson setup build -Ddefault_library=static + - name: Compile - run: ninja -C obj-x86_64-pc-linux-gnu + run: ninja -C build noxwayland: name: "Build Hyprland in pure Wayland (Arch)" @@ -86,24 +69,17 @@ jobs: container: image: archlinux steps: - - name: Download dependencies - run: | - sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf - pacman --noconfirm --noprogressbar -Syyu - pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd libliftoff tomlplusplus - - name: Set up user - run: | - useradd -m githubuser - echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers - - name: Install libdisplay-info from the AUR - run: | - su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar" - - name: Checkout Hyprland - uses: actions/checkout@v3 + - name: Checkout repository actions + uses: actions/checkout@v4 with: - submodules: true + sparse-checkout: .github/actions + + - name: Setup base + uses: ./.github/actions/setup_base + - name: Configure - run: mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DNO_XWAYLAND:STRING=true -H./ -B./build -G Ninja + run: mkdir -p build && cmake --no-warn-unused-cli -DCMAKE_BUILD_TYPE:STRING=Release -DNO_XWAYLAND:STRING=true -H./ -B./build -G Ninja + - name: Compile run: make release @@ -113,25 +89,16 @@ jobs: container: image: archlinux steps: - - name: Download dependencies - run: | - sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf - pacman --noconfirm --noprogressbar -Syyu - pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers git go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd cmake jq python libliftoff tomlplusplus - - name: Set up user - run: | - useradd -m githubuser - echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers - - name: Install libdisplay-info from the AUR - run: | - su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar" - - name: Checkout Hyprland - uses: actions/checkout@v3 + - name: Checkout repository actions + uses: actions/checkout@v4 with: - submodules: true + sparse-checkout: .github/actions + + - name: Setup base + uses: ./.github/actions/setup_base + - name: Configure - run: | - meson obj-x86_64-pc-linux-gnu \ - -Ddefault_library=static + run: meson setup build -Ddefault_library=static + - name: clang-format check - run: ninja -C obj-x86_64-pc-linux-gnu clang-format-check + run: ninja -C build clang-format-check diff --git a/.github/workflows/security-checks.yml b/.github/workflows/security-checks.yml index 644aa29d..6a86f70e 100644 --- a/.github/workflows/security-checks.yml +++ b/.github/workflows/security-checks.yml @@ -24,13 +24,13 @@ jobs: uses: github/codeql-action/upload-sarif@v2 with: sarif_file: ${{github.workspace}}/flawfinder_results.sarif - + codeql: name: CodeQL runs-on: ubuntu-latest container: image: archlinux - + permissions: actions: read contents: read @@ -42,34 +42,25 @@ jobs: language: [ 'cpp' ] steps: - - name: Checkout repository - uses: actions/checkout@v3 + - name: Checkout repository actions + uses: actions/checkout@v4 + with: + sparse-checkout: .github/actions - name: Initialize CodeQL uses: github/codeql-action/init@v2 with: languages: ${{ matrix.language }} - - name: Init Hyprland build - run: | - sed -i 's/SigLevel = Required DatabaseOptional/SigLevel = Optional TrustAll/' /etc/pacman.conf - pacman --noconfirm --noprogressbar -Syyu - pacman --noconfirm --noprogressbar -Sy glslang libepoxy libfontenc libxcvt libxfont2 libxkbfile vulkan-headers vulkan-validation-layers xcb-util-errors xcb-util-renderutil xcb-util-wm xorg-fonts-encodings xorg-server-common xorg-setxkbmap xorg-xkbcomp xorg-xwayland git cmake go clang lld libc++ pkgconf meson ninja wayland wayland-protocols libinput libxkbcommon pixman glm libdrm libglvnd cairo pango systemd scdoc base-devel seatd python libliftoff tomlplusplus - useradd -m githubuser - echo -e "root ALL=(ALL:ALL) ALL\ngithubuser ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers - su githubuser -c "cd ~ && git clone https://aur.archlinux.org/libdisplay-info.git && cd ./libdisplay-info && makepkg -si --skippgpcheck --noconfirm --noprogressbar" - git config --global --add safe.directory /__w/Hyprland/Hyprland - - - name: Checkout Hyprland - uses: actions/checkout@v3 + - name: Setup base + uses: ./.github/actions/setup_base with: - submodules: recursive + INSTALL_XORG_PKGS: true - name: Build Hyprland run: | - git submodule sync --recursive && git submodule update --init --force --recursive make all - + - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 with: From d02ba422daae97498ffe6cdf84914b74ddf1fd44 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 10 Dec 2023 19:30:14 +0000 Subject: [PATCH 366/513] hyprpm: guard empty command fixes #4114 --- hyprpm/src/main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hyprpm/src/main.cpp b/hyprpm/src/main.cpp index e6191e66..7bc44141 100644 --- a/hyprpm/src/main.cpp +++ b/hyprpm/src/main.cpp @@ -58,6 +58,11 @@ int main(int argc, char** argv, char** envp) { } } + if (command.empty()) { + std::cout << HELP; + return 0; + } + g_pPluginManager = std::make_unique(); g_pPluginManager->m_bVerbose = verbose; From 167f2ed3b2bb18ceeabb831ac80b655ef8e16867 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 10 Dec 2023 19:32:03 +0000 Subject: [PATCH 367/513] border: fix failed assert on small windows fixes #4115 --- src/render/decorations/CHyprBorderDecoration.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index 560eb8ca..4b3abd8c 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -51,6 +51,11 @@ void CHyprBorderDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& of if (m_bAssignedGeometry.width < m_seExtents.topLeft.x + 1 || m_bAssignedGeometry.height < m_seExtents.topLeft.y + 1) return; + CBox windowBox = assignedBoxGlobal().translate(-pMonitor->vecPosition).expand(-m_pWindow->getRealBorderSize()).scale(pMonitor->scale).round(); + + if (windowBox.width < 1 || windowBox.height < 1) + return; + auto grad = m_pWindow->m_cRealBorderColor; const bool ANIMATED = m_pWindow->m_fBorderFadeAnimationProgress.isBeingAnimated(); float a1 = a * (ANIMATED ? m_pWindow->m_fBorderFadeAnimationProgress.fl() : 1.f); @@ -60,8 +65,6 @@ void CHyprBorderDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& of grad.m_fAngle = normalizeAngleRad(grad.m_fAngle); } - CBox windowBox = assignedBoxGlobal().translate(-pMonitor->vecPosition).expand(-m_pWindow->getRealBorderSize()).scale(pMonitor->scale).round(); - int borderSize = m_pWindow->getRealBorderSize(); const auto ROUNDING = m_pWindow->rounding() * pMonitor->scale; From 53ce7992beef6320edc40e167b7bf6cc81f9bec2 Mon Sep 17 00:00:00 2001 From: nmzik Date: Mon, 11 Dec 2023 17:28:22 +0100 Subject: [PATCH 368/513] renderer: double lookup fix, input: double conversion fix (#4124) --- src/managers/input/InputManager.cpp | 4 ++-- src/render/OpenGL.cpp | 27 +++++++++++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 284b4da6..374f217b 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -853,7 +853,7 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) { pKeyboard->repeatDelay = REPEATDELAY; pKeyboard->repeatRate = REPEATRATE; pKeyboard->numlockOn = NUMLOCKON; - pKeyboard->xkbFilePath = FILEPATH.c_str(); + pKeyboard->xkbFilePath = FILEPATH; xkb_rule_names rules = {.rules = RULES.c_str(), .model = MODEL.c_str(), .layout = LAYOUT.c_str(), .variant = VARIANT.c_str(), .options = OPTIONS.c_str()}; @@ -1586,7 +1586,7 @@ void CInputManager::destroySwitch(SSwitchDevice* pDevice) { } void CInputManager::setCursorImageUntilUnset(std::string name) { - g_pHyprRenderer->setCursorFromName(name.c_str()); + g_pHyprRenderer->setCursorFromName(name); m_bCursorImageOverridden = true; m_sCursorSurfaceInfo.inUse = false; } diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index da348a0f..cb468932 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2024,16 +2024,23 @@ void CHyprOpenGLImpl::clearWithTex() { void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) { g_pHyprRenderer->makeEGLCurrent(); - g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].mirrorFB.release(); - g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].offloadFB.release(); - g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].mirrorSwapFB.release(); - g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].monitorMirrorFB.release(); - g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].blurFB.release(); - g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].offMainFB.release(); - g_pHyprOpenGL->m_mMonitorRenderResources[pMonitor].stencilTex.destroyTexture(); - g_pHyprOpenGL->m_mMonitorBGTextures[pMonitor].destroyTexture(); - g_pHyprOpenGL->m_mMonitorRenderResources.erase(pMonitor); - g_pHyprOpenGL->m_mMonitorBGTextures.erase(pMonitor); + auto RESIT = g_pHyprOpenGL->m_mMonitorRenderResources.find(pMonitor); + if (RESIT != g_pHyprOpenGL->m_mMonitorRenderResources.end()) { + RESIT->second.mirrorFB.release(); + RESIT->second.offloadFB.release(); + RESIT->second.mirrorSwapFB.release(); + RESIT->second.monitorMirrorFB.release(); + RESIT->second.blurFB.release(); + RESIT->second.offMainFB.release(); + RESIT->second.stencilTex.destroyTexture(); + g_pHyprOpenGL->m_mMonitorRenderResources.erase(RESIT); + } + + auto TEXIT = g_pHyprOpenGL->m_mMonitorBGTextures.find(pMonitor); + if (TEXIT != g_pHyprOpenGL->m_mMonitorBGTextures.end()) { + TEXIT->second.destroyTexture(); + g_pHyprOpenGL->m_mMonitorBGTextures.erase(TEXIT); + } Debug::log(LOG, "Monitor {} -> destroyed all render data", pMonitor->szName); } From 50648e6bae05136190d604c8cfc585c91dedaa91 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Mon, 11 Dec 2023 16:29:04 +0000 Subject: [PATCH 369/513] hyprpm: cast std::clamp args to be of the same type (#4116) hyprpm/src/progress/CProgressBar.cpp:50:27: error: no matching function for call to 'clamp' const auto BARWIDTH = std::clamp(w.ws_col - m_szCurrentMessage.length() - 2, 0UL, 50UL); ^~~~~~~~~~ /usr/include/c++/v1/__algorithm/clamp.h:38:1: note: candidate template ignored: deduced conflicting types for parameter '_Tp' ('size_type' (aka 'unsigned int') vs. 'unsigned long') clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi) ^ /usr/include/c++/v1/__algorithm/clamp.h:27:1: note: candidate function template not viable: requires 4 arguments, but 3 were provided clamp(const _Tp& __v, const _Tp& __lo, const _Tp& __hi, _Compare __comp) ^ --- hyprpm/src/progress/CProgressBar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hyprpm/src/progress/CProgressBar.cpp b/hyprpm/src/progress/CProgressBar.cpp index 69f51dd2..45602f82 100644 --- a/hyprpm/src/progress/CProgressBar.cpp +++ b/hyprpm/src/progress/CProgressBar.cpp @@ -47,7 +47,7 @@ void CProgressBar::print() { else percentDone = (float)m_iSteps / (float)m_iMaxSteps; - const auto BARWIDTH = std::clamp(w.ws_col - m_szCurrentMessage.length() - 2, 0UL, 50UL); + const auto BARWIDTH = std::clamp(w.ws_col - static_cast(m_szCurrentMessage.length()) - 2, 0UL, 50UL); // draw bar message += std::string{" "} + Colors::GREEN; From 0fdf909b196ffb5730bcf52c1195eabeb2b04d3c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 11 Dec 2023 16:32:00 +0000 Subject: [PATCH 370/513] renderer: don't render decorations on renderdata.decorate false fixes #4117 --- src/render/Renderer.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 6731dff5..43d7584c 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -479,7 +479,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* } } - if (!pWindow->m_bIsFullscreen || PWORKSPACE->m_efFullscreenMode != FULLSCREEN_FULL) { + if (decorate) { for (auto& wd : pWindow->m_dWindowDecorations) { if (wd->getDecorationLayer() != DECORATION_LAYER_BOTTOM) continue; @@ -511,11 +511,13 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false; - for (auto& wd : pWindow->m_dWindowDecorations) { - if (wd->getDecorationLayer() != DECORATION_LAYER_OVER) - continue; + if (decorate) { + for (auto& wd : pWindow->m_dWindowDecorations) { + if (wd->getDecorationLayer() != DECORATION_LAYER_OVER) + continue; - wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, Vector2D{renderdata.x, renderdata.y} - PREOFFSETPOS); + wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, Vector2D{renderdata.x, renderdata.y} - PREOFFSETPOS); + } } if (TRANSFORMERSPRESENT) { @@ -553,11 +555,13 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* g_pHyprOpenGL->m_RenderData.useNearestNeighbor = false; } - for (auto& wd : pWindow->m_dWindowDecorations) { - if (wd->getDecorationLayer() != DECORATION_LAYER_OVERLAY) - continue; + if (decorate) { + for (auto& wd : pWindow->m_dWindowDecorations) { + if (wd->getDecorationLayer() != DECORATION_LAYER_OVERLAY) + continue; - wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, Vector2D{renderdata.x, renderdata.y} - PREOFFSETPOS); + wd->draw(pMonitor, renderdata.alpha * renderdata.fadeAlpha, Vector2D{renderdata.x, renderdata.y} - PREOFFSETPOS); + } } } From 8191e635a33ea634846f6458b42685da277f50b5 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 11 Dec 2023 16:46:20 +0000 Subject: [PATCH 371/513] deco-positioner: include sticky in sent geometry --- src/render/decorations/DecorationPositioner.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index 30e49ac1..bdf37e58 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -227,28 +227,28 @@ void CDecorationPositioner::onWindowUpdate(CWindow* pWindow) { stickyOffsetYT += desiredSize; stickyOffsetYB += desiredSize; } else if (LEFT) { - pos = wb.pos() - EDGEPOINT - Vector2D{stickyOffsetXL, 0}; + pos = wb.pos() - EDGEPOINT - Vector2D{stickyOffsetXL, -stickyOffsetYT}; pos.x -= desiredSize; - size = {desiredSize, wb.size().y}; + size = {desiredSize, wb.size().y + stickyOffsetYB + stickyOffsetYT}; if (SOLID) stickyOffsetXL += desiredSize; } else if (RIGHT) { - pos = wb.pos() + Vector2D{wb.size().x, 0} - EDGEPOINT + Vector2D{stickyOffsetXR, 0}; - size = {desiredSize, wb.size().y}; + pos = wb.pos() + Vector2D{wb.size().x, 0} - EDGEPOINT + Vector2D{stickyOffsetXR, -stickyOffsetYT}; + size = {desiredSize, wb.size().y + stickyOffsetYB + stickyOffsetYT}; if (SOLID) stickyOffsetXR += desiredSize; } else if (TOP) { - pos = wb.pos() - EDGEPOINT - Vector2D{0, stickyOffsetYT}; + pos = wb.pos() - EDGEPOINT - Vector2D{stickyOffsetXL, stickyOffsetYT}; pos.y -= desiredSize; - size = {wb.size().x, desiredSize}; + size = {wb.size().x + stickyOffsetXL + stickyOffsetXR, desiredSize}; if (SOLID) stickyOffsetYT += desiredSize; } else { - pos = wb.pos() + Vector2D{0, wb.size().y} - EDGEPOINT - Vector2D{0, stickyOffsetYB}; - size = {wb.size().x, desiredSize}; + pos = wb.pos() + Vector2D{0, wb.size().y} - EDGEPOINT - Vector2D{stickyOffsetXL, stickyOffsetYB}; + size = {wb.size().x + stickyOffsetXL + stickyOffsetXR, desiredSize}; if (SOLID) stickyOffsetYB += desiredSize; From e53134ca904e47a24191ea028c019ac9728b7dad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Conzelmann?= <45296195+zephvr@users.noreply.github.com> Date: Mon, 11 Dec 2023 17:51:10 +0100 Subject: [PATCH 372/513] internal: fix interactions with fakefullscreen (#4113) - In a maximized window, unstuck fakefullscreen from on state - In a fakefullscreen window, going in and out of fullscreen state keep the fakefullscreen state rendered --- src/Compositor.cpp | 2 +- src/Window.cpp | 5 +++++ src/Window.hpp | 1 + src/managers/KeybindManager.cpp | 3 +-- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index f3d048a9..2618ad39 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2257,7 +2257,7 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode g_pLayoutManager->getCurrentLayout()->fullscreenRequestForWindow(pWindow, MODE, on); - g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->m_bIsFullscreen && MODE == FULLSCREEN_FULL); + g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->shouldSendFullscreenState()); pWindow->updateDynamicRules(); updateWindowAnimatedDecorationValues(pWindow); diff --git a/src/Window.cpp b/src/Window.cpp index 58ec5c72..bd51f2ff 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -1000,3 +1000,8 @@ int CWindow::getRealBorderSize() { bool CWindow::canBeTorn() { return (m_sAdditionalConfigData.forceTearing.toUnderlying() || m_bTearingHint) && g_pHyprRenderer->m_bTearingEnvSatisfied; } + +bool CWindow::shouldSendFullscreenState() { + const auto MODE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID)->m_efFullscreenMode; + return m_bFakeFullscreenState || (m_bIsFullscreen && (MODE == FULLSCREEN_FULL)); +} diff --git a/src/Window.hpp b/src/Window.hpp index 810400d7..c4f2a15d 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -366,6 +366,7 @@ class CWindow { bool opaque(); float rounding(); bool canBeTorn(); + bool shouldSendFullscreenState(); int getRealBorderSize(); void updateSpecialRenderData(); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 2046b867..6aea4e32 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1918,8 +1918,7 @@ void CKeybindManager::fakeFullscreenActive(std::string args) { if (g_pCompositor->m_pLastWindow) { // will also set the flag g_pCompositor->m_pLastWindow->m_bFakeFullscreenState = !g_pCompositor->m_pLastWindow->m_bFakeFullscreenState; - g_pXWaylandManager->setWindowFullscreen(g_pCompositor->m_pLastWindow, - g_pCompositor->m_pLastWindow->m_bFakeFullscreenState || g_pCompositor->m_pLastWindow->m_bIsFullscreen); + g_pXWaylandManager->setWindowFullscreen(g_pCompositor->m_pLastWindow, g_pCompositor->m_pLastWindow->shouldSendFullscreenState()); } } From ea7569d7e0941d19f5f469a5fbb79bc0fa62b935 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 11 Dec 2023 22:58:40 +0000 Subject: [PATCH 373/513] config: improve layoutopt handling for workspacerules --- src/config/ConfigManager.cpp | 16 ++++++++++++++-- src/config/ConfigManager.hpp | 30 +++++++++++++++--------------- src/layout/MasterLayout.cpp | 13 ++++++------- 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 5eb26efc..75def1dd 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1227,8 +1227,20 @@ void CConfigManager::handleWorkspaceRules(const std::string& command, const std: wsRule.isPersistent = configStringToInt(rule.substr(delim + 11)); else if ((delim = rule.find(ruleOnCreatedEmtpy)) != std::string::npos) wsRule.onCreatedEmptyRunCmd = cleanCmdForWorkspace(name, rule.substr(delim + ruleOnCreatedEmtpyLen)); - else if ((delim = rule.find("layoutopt:orientation:")) != std::string::npos) - wsRule.layoutopts["orientation"] = rule.substr(delim + 22); + else if ((delim = rule.find("layoutopt:")) != std::string::npos) { + std::string opt = rule.substr(delim + 10); + if (!opt.contains(":")) { + // invalid + Debug::log(ERR, "Invalid workspace rule found: {}", rule); + parseError = "Invalid workspace rule found: " + rule; + return; + } + + std::string val = opt.substr(opt.find(":") + 1); + opt = opt.substr(0, opt.find(":")); + + wsRule.layoutopts[opt] = val; + } }; size_t pos = 0; diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 8009100e..d5957cd5 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -37,21 +37,21 @@ struct SConfigValue { }; struct SWorkspaceRule { - std::string monitor = ""; - std::string workspaceString = ""; - std::string workspaceName = ""; - int workspaceId = -1; - bool isDefault = false; - bool isPersistent = false; - std::optional gapsIn; - std::optional gapsOut; - std::optional borderSize; - std::optional border; - std::optional rounding; - std::optional decorate; - std::optional shadow; - std::optional onCreatedEmptyRunCmd; - std::map layoutopts; + std::string monitor = ""; + std::string workspaceString = ""; + std::string workspaceName = ""; + int workspaceId = -1; + bool isDefault = false; + bool isPersistent = false; + std::optional gapsIn; + std::optional gapsOut; + std::optional borderSize; + std::optional border; + std::optional rounding; + std::optional decorate; + std::optional shadow; + std::optional onCreatedEmptyRunCmd; + std::map layoutopts; }; struct SMonitorAdditionalReservedArea { diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 8b12d669..ff7f9e2e 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -45,10 +45,8 @@ SMasterWorkspaceData* CHyprMasterLayout::getMasterWorkspaceData(const int& ws) { const auto layoutoptsForWs = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(ws)).layoutopts; auto orientationForWs = *orientation; - try { - if (layoutoptsForWs.contains("orientation")) - orientationForWs = std::any_cast(layoutoptsForWs.at("orientation")); - } catch (std::exception& e) { Debug::log(ERR, "Error from layoutopt rules: {}", e.what()); } + if (layoutoptsForWs.contains("orientation")) + orientationForWs = layoutoptsForWs.at("orientation"); if (orientationForWs == "top") { PWORKSPACEDATA->orientation = ORIENTATION_TOP; @@ -56,11 +54,12 @@ SMasterWorkspaceData* CHyprMasterLayout::getMasterWorkspaceData(const int& ws) { PWORKSPACEDATA->orientation = ORIENTATION_RIGHT; } else if (orientationForWs == "bottom") { PWORKSPACEDATA->orientation = ORIENTATION_BOTTOM; - } else if (orientationForWs == "left") { - PWORKSPACEDATA->orientation = ORIENTATION_LEFT; - } else { + } else if (orientationForWs == "center") { PWORKSPACEDATA->orientation = ORIENTATION_CENTER; + } else { + PWORKSPACEDATA->orientation = ORIENTATION_LEFT; } + return PWORKSPACEDATA; } From accb3d8d0b339ce83dd36704503253d874c7163b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 12 Dec 2023 01:14:36 +0000 Subject: [PATCH 374/513] xwayland: push invisible windows outside layout fixes some xwl focus issues with special especially. --- src/Compositor.cpp | 2 +- src/helpers/Monitor.cpp | 27 ++++++++++++++++++++++++++- src/managers/XWaylandManager.cpp | 4 +++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 2618ad39..3b022a19 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2773,4 +2773,4 @@ void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scal void CCompositor::setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform) { wlr_surface_set_preferred_buffer_transform(pSurface, transform); -} +} \ No newline at end of file diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index c112d07d..0132db63 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -565,6 +565,15 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool g_pCompositor->updateFullscreenFadeOnWorkspace(pWorkspace); g_pConfigManager->ensureVRR(this); + + for (auto& w : g_pCompositor->m_vWindows) { + if (w->m_iWorkspaceID != POLDWORKSPACE->m_iID || !w->m_bMappedX11 || !w->m_bIsX11 || w->isHidden() || w->m_iMonitorID != ID) + continue; + + g_pXWaylandManager->moveXWaylandWindow(w.get(), {30000, 30000}); + } + + g_pCompositor->forceReportSizesToWindowsOnWorkspace(pWorkspace->m_iID); } void CMonitor::changeWorkspace(const int& id, bool internal) { @@ -576,7 +585,9 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) { if (!pWorkspace) { // remove special if exists - if (const auto EXISTINGSPECIAL = g_pCompositor->getWorkspaceByID(specialWorkspaceID); EXISTINGSPECIAL) { + const auto EXISTINGSPECIAL = g_pCompositor->getWorkspaceByID(specialWorkspaceID); + + if (EXISTINGSPECIAL) { EXISTINGSPECIAL->startAnim(false, false); g_pEventManager->postEvent(SHyprIPCEvent{"activespecial", "," + szName}); } @@ -590,6 +601,18 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) { else g_pInputManager->refocus(); + // for xwayland: yeet all the windows to narnia to avoid some focus fuckery. I hate xwayland. + // I'll avoid setting XCB_ICCCM_WM_STATE_ICONIC (aka minimized) so that the apps don't do stupid shit. + + if (EXISTINGSPECIAL) { + for (auto& w : g_pCompositor->m_vWindows) { + if (w->m_iWorkspaceID != EXISTINGSPECIAL->m_iID || !w->m_bMappedX11 || !w->m_bIsX11 || w->isHidden() || w->m_iMonitorID != ID) + continue; + + g_pXWaylandManager->moveXWaylandWindow(w.get(), {30000, 30000}); + } + } + return; } @@ -631,6 +654,8 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) { g_pEventManager->postEvent(SHyprIPCEvent{"activespecial", pWorkspace->m_szName + "," + szName}); g_pHyprRenderer->damageMonitor(this); + + g_pCompositor->forceReportSizesToWindowsOnWorkspace(specialWorkspaceID); } void CMonitor::setSpecialWorkspace(const int& id) { diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 2883f205..dcb706e3 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -262,7 +262,9 @@ void CHyprXWaylandManager::moveXWaylandWindow(CWindow* pWindow, const Vector2D& if (!pWindow->m_bIsX11) return; - wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pos.x, pos.y, pWindow->m_vRealSize.vec().x, pWindow->m_vRealSize.vec().y); + Vector2D size = pWindow->m_vRealSize.goalv() * pWindow->m_fX11SurfaceScaledBy; + + wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pos.x, pos.y, size.x, size.y); } void CHyprXWaylandManager::checkBorders(CWindow* pWindow) { From 8f3848788422822c2cb36c57b4f3929eec1cc42c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 12 Dec 2023 01:15:17 +0000 Subject: [PATCH 375/513] xwayland: don't change workspace on configure for invisible windows fixes #3578 --- src/events/Windows.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index ff68d13f..2c107999 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -1062,6 +1062,13 @@ void Events::listener_configureX11(void* owner, void* data) { wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height); + PWINDOW->m_vReportedSize = {E->width, E->height}; + + PWINDOW->updateWindowDecos(); + + if (!g_pCompositor->isWorkspaceVisible(PWINDOW->m_iWorkspaceID)) + return; // further things are only for visible windows + PWINDOW->m_iWorkspaceID = g_pCompositor->getMonitorFromVector(PWINDOW->m_vRealPosition.vec() + PWINDOW->m_vRealSize.vec() / 2.f)->activeWorkspace; g_pCompositor->changeWindowZOrder(PWINDOW, true); @@ -1072,10 +1079,6 @@ void Events::listener_configureX11(void* owner, void* data) { g_pInputManager->refocus(); g_pHyprRenderer->damageWindow(PWINDOW); - - PWINDOW->updateWindowDecos(); - - PWINDOW->m_vReportedSize = {E->width, E->height}; } void Events::listener_unmanagedSetGeometry(void* owner, void* data) { From 1950c3fc9c807f10735b0a681aca49fd2d0d2d0b Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 12 Dec 2023 14:55:48 +0000 Subject: [PATCH 376/513] input: unset resize cursor on empty focus fixes #4133 --- src/managers/input/InputManager.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 374f217b..8b4b51bc 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -319,7 +319,11 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { if (!foundSurface) { if (!m_bEmptyFocusCursorSet) { - m_eBorderIconDirection = BORDERICON_NONE; + if (*PRESIZEONBORDER && *PRESIZECURSORICON && m_eBorderIconDirection != BORDERICON_NONE) { + m_eBorderIconDirection = BORDERICON_NONE; + unsetCursorImage(); + } + if (g_pHyprRenderer->m_bHasARenderedCursor) { // TODO: maybe wrap? if (m_ecbClickBehavior == CLICKMODE_KILL) From ba2af6f86d26fbf4b51aa37bf901e0118f46bbe3 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 12 Dec 2023 14:58:43 +0000 Subject: [PATCH 377/513] focus: prefer sendMotionEventsToFocused for ensuring cursor image --- src/Compositor.cpp | 4 ++-- src/events/Layers.cpp | 2 +- src/events/Windows.cpp | 6 ++---- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 3b022a19..0eb1b00a 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1989,7 +1989,7 @@ void CCompositor::swapActiveWorkspaces(CMonitor* pMonitorA, CMonitor* pMonitorB) updateFullscreenFadeOnWorkspace(PWORKSPACEB); updateFullscreenFadeOnWorkspace(PWORKSPACEA); - g_pInputManager->simulateMouseMovement(); + g_pInputManager->sendMotionEventsToFocused(); // event g_pEventManager->postEvent(SHyprIPCEvent{"moveworkspace", PWORKSPACEA->m_szName + "," + pMonitorB->szName}); @@ -2174,7 +2174,7 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni wlr_cursor_warp(m_sWLRCursor, nullptr, pMonitor->vecPosition.x + pMonitor->vecTransformedSize.x / 2, pMonitor->vecPosition.y + pMonitor->vecTransformedSize.y / 2); - g_pInputManager->simulateMouseMovement(); + g_pInputManager->sendMotionEventsToFocused(); } // finalize diff --git a/src/events/Layers.cpp b/src/events/Layers.cpp index a9d8b5d0..d6e21d9d 100644 --- a/src/events/Layers.cpp +++ b/src/events/Layers.cpp @@ -255,7 +255,7 @@ void Events::listener_unmapLayerSurface(void* owner, void* data) { (int)layersurface->layerSurface->surface->current.width, (int)layersurface->layerSurface->surface->current.height}; g_pHyprRenderer->damageBox(&geomFixed); - g_pInputManager->simulateMouseMovement(); + g_pInputManager->sendMotionEventsToFocused(); } void Events::listener_commitLayerSurface(void* owner, void* data) { diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 2c107999..efefcbec 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -641,8 +641,7 @@ void Events::listener_mapWindow(void* owner, void* data) { g_pCompositor->setPreferredScaleForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->scale); g_pCompositor->setPreferredTransformForSurface(PWINDOW->m_pWLSurface.wlr(), PMONITOR->transform); - if (g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal()) == g_pCompositor->m_pLastWindow) - g_pInputManager->simulateMouseMovement(); + g_pInputManager->sendMotionEventsToFocused(); // fix some xwayland apps that don't behave nicely PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; @@ -737,8 +736,7 @@ void Events::listener_unmapWindow(void* owner, void* data) { if (PWINDOWCANDIDATE != g_pCompositor->m_pLastWindow && PWINDOWCANDIDATE) g_pCompositor->focusWindow(PWINDOWCANDIDATE); - if (g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal()) == PWINDOWCANDIDATE) - g_pInputManager->simulateMouseMovement(); + g_pInputManager->sendMotionEventsToFocused(); // CWindow::onUnmap will remove this window's active status, but we can't really do it above. if (PWINDOW == g_pCompositor->m_pLastWindow || !g_pCompositor->m_pLastWindow) { From 934112af5bed36a1273cc0d5588e27ab4825922b Mon Sep 17 00:00:00 2001 From: dranull <150595692+dranull@users.noreply.github.com> Date: Tue, 12 Dec 2023 16:43:38 +0000 Subject: [PATCH 378/513] config: Use canonical instead of read_symlink (#4136) --- src/main.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 0f68c3b2..86c44857 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -52,19 +52,21 @@ int main(int argc, char** argv) { return 1; } - std::string next_arg = std::next(it)->c_str(); + configPath = std::next(it)->c_str(); - if (std::filesystem::is_symlink(next_arg)) - next_arg = std::filesystem::read_symlink(next_arg); + try { + configPath = std::filesystem::canonical(configPath); - if (!std::filesystem::is_regular_file(next_arg)) { - std::cerr << "[ ERROR ] Config file '" << next_arg << "' doesn't exist!\n"; + if (!std::filesystem::is_regular_file(configPath)) { + throw std::exception(); + } + } catch (...) { + std::cerr << "[ ERROR ] Config file '" << configPath << "' doesn't exist!\n"; help(); return 1; } - configPath = std::filesystem::weakly_canonical(next_arg); Debug::log(LOG, "User-specified config location: '{}'", configPath); it++; From 4de986072c12af8081f877f4792d57b4a11a0a6a Mon Sep 17 00:00:00 2001 From: dranull <150595692+dranull@users.noreply.github.com> Date: Tue, 12 Dec 2023 16:44:31 +0000 Subject: [PATCH 379/513] layout: Focus a floating window after closing the last tiled (#4137) --- src/layout/IHyprLayout.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index acd84684..0c6d24fd 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -565,13 +565,19 @@ CWindow* IHyprLayout::getNextWindowCandidate(CWindow* pWindow) { } // if it was a tiled window, we first try to find the window that will replace it. - const auto PWINDOWCANDIDATE = g_pCompositor->vectorToWindowIdeal(pWindow->middle()); + auto pWindowCandidate = g_pCompositor->vectorToWindowIdeal(pWindow->middle()); - if (!PWINDOWCANDIDATE || pWindow == PWINDOWCANDIDATE || !PWINDOWCANDIDATE->m_bIsMapped || PWINDOWCANDIDATE->isHidden() || PWINDOWCANDIDATE->m_bX11ShouldntFocus || - PWINDOWCANDIDATE->m_iX11Type == 2 || PWINDOWCANDIDATE->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) + if (!pWindowCandidate) + pWindowCandidate = g_pCompositor->getTopLeftWindowOnWorkspace(pWindow->m_iWorkspaceID); + + if (!pWindowCandidate) + pWindowCandidate = g_pCompositor->getFirstWindowOnWorkspace(pWindow->m_iWorkspaceID); + + if (!pWindowCandidate || pWindow == pWindowCandidate || !pWindowCandidate->m_bIsMapped || pWindowCandidate->isHidden() || pWindowCandidate->m_bX11ShouldntFocus || + pWindowCandidate->m_iX11Type == 2 || pWindowCandidate->m_iMonitorID != g_pCompositor->m_pLastMonitor->ID) return nullptr; - return PWINDOWCANDIDATE; + return pWindowCandidate; } bool IHyprLayout::isWindowReachable(CWindow* pWindow) { From d9bc210285c1971afd9abe9fbe89a5a14c8df2a7 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Tue, 12 Dec 2023 23:34:21 +0200 Subject: [PATCH 380/513] Nix: remove libdrm override Nixpkgs update has the new version. --- flake.lock | 12 ++++++------ nix/default.nix | 12 +----------- nix/overlays.nix | 24 ------------------------ nix/wlroots.nix | 25 +++++++------------------ 4 files changed, 14 insertions(+), 59 deletions(-) diff --git a/flake.lock b/flake.lock index a7743fd0..8b7aa952 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1700612854, - "narHash": "sha256-yrQ8osMD+vDLGFX7pcwsY/Qr5PUd6OmDMYJZzZi0+zc=", + "lastModified": 1702312524, + "narHash": "sha256-gkZJRDBUCpTPBvQk25G0B7vfbpEYM5s5OZqghkjZsnE=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "19cbff58383a4ae384dea4d1d0c823d72b49d614", + "rev": "a9bf124c46ef298113270b1f84a164865987a91c", "type": "github" }, "original": { @@ -95,11 +95,11 @@ ] }, "locked": { - "lastModified": 1700508250, - "narHash": "sha256-X4o/mifI7Nhu0UKYlxx53wIC+gYDo3pVM9L2u3PE2bE=", + "lastModified": 1702334919, + "narHash": "sha256-ibOZ3TLjqndGMcj2f+07NFwDWoum4IbzF58byZuJJNg=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "eb120ff25265ecacd0fc13d7dab12131b60d0f47", + "rev": "f5c3576c3b6cb1c31a8dfa3e4113f59bfe40cd71", "type": "github" }, "original": { diff --git a/nix/default.nix b/nix/default.nix index 68b1bb22..d80a42a9 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -40,16 +40,6 @@ nvidiaPatches ? false, hidpiXWayland ? false, }: -let - # NOTE: remove after https://github.com/NixOS/nixpkgs/pull/271096 reaches nixos-unstable - libdrm_2_4_118 = libdrm.overrideAttrs(attrs: rec { - version = "2.4.118"; - src = fetchurl { - url = "https://dri.freedesktop.org/${attrs.pname}/${attrs.pname}-${version}.tar.xz"; - hash = "sha256-p3e9hfK1/JxX+IbIIFgwBXgxfK/bx30Kdp1+mpVnq4g="; - }; - }); -in assert lib.assertMsg (!nvidiaPatches) "The option `nvidiaPatches` has been removed."; assert lib.assertMsg (!enableNvidiaPatches) "The option `enableNvidiaPatches` has been removed."; assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been removed. Please refer https://wiki.hyprland.org/Configuring/XWayland"; @@ -85,7 +75,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov cairo git hyprland-protocols - libdrm_2_4_118 + libdrm libGL libinput libxkbcommon diff --git a/nix/overlays.nix b/nix/overlays.nix index 9ad623fe..60ebd574 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -70,30 +70,6 @@ in { wlroots-hyprland = final.callPackage ./wlroots.nix { version = "${mkDate (inputs.wlroots.lastModifiedDate or "19700101")}_${inputs.wlroots.shortRev or "dirty"}"; src = inputs.wlroots; - - libdisplay-info = prev.libdisplay-info.overrideAttrs (old: { - version = "0.1.1+date=2023-03-02"; - src = final.fetchFromGitLab { - domain = "gitlab.freedesktop.org"; - owner = "emersion"; - repo = old.pname; - rev = "147d6611a64a6ab04611b923e30efacaca6fc678"; - sha256 = "sha256-/q79o13Zvu7x02SBGu0W5yQznQ+p7ltZ9L6cMW5t/o4="; - }; - }); - - libliftoff = prev.libliftoff.overrideAttrs (old: { - version = "0.5.0-dev"; - src = final.fetchFromGitLab { - domain = "gitlab.freedesktop.org"; - owner = "emersion"; - repo = old.pname; - rev = "d98ae243280074b0ba44bff92215ae8d785658c0"; - sha256 = "sha256-DjwlS8rXE7srs7A8+tHqXyUsFGtucYSeq6X0T/pVOc8="; - }; - - NIX_CFLAGS_COMPILE = toString ["-Wno-error=sign-conversion"]; - }); }; }; } diff --git a/nix/wlroots.nix b/nix/wlroots.nix index 0b9186e9..005762c3 100644 --- a/nix/wlroots.nix +++ b/nix/wlroots.nix @@ -1,33 +1,22 @@ { - fetchurl, version, src, wlroots, hwdata, libdisplay-info, libliftoff, - libdrm, enableXWayland ? true, }: -let - # NOTE: remove after https://github.com/NixOS/nixpkgs/pull/271096 reaches nixos-unstable - libdrm_2_4_118 = libdrm.overrideAttrs(old: rec { - version = "2.4.118"; - src = fetchurl { - url = "https://dri.freedesktop.org/${old.pname}/${old.pname}-${version}.tar.xz"; - hash = "sha256-p3e9hfK1/JxX+IbIIFgwBXgxfK/bx30Kdp1+mpVnq4g="; - }; - }); -in wlroots.overrideAttrs (old: { inherit version src enableXWayland; pname = "${old.pname}-hyprland"; - # HACK: libdrm_2_4_118 is placed at the head of list to take precedence over libdrm in `old.buildInputs` - buildInputs = [libdrm_2_4_118] ++ old.buildInputs ++ [hwdata libliftoff libdisplay-info]; - - NIX_CFLAGS_COMPILE = toString [ - "-Wno-error=maybe-uninitialized" - ]; + buildInputs = + old.buildInputs + ++ [ + hwdata + libliftoff + libdisplay-info + ]; }) From 4190b967186e50d00ea3dc636e9f3ec40639dd03 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 13 Dec 2023 02:32:57 +0000 Subject: [PATCH 381/513] hyprpm: add duplicate header error and log more verbose in install fails --- hyprpm/src/core/PluginManager.cpp | 33 ++++++++++++++++++++++--------- hyprpm/src/core/PluginManager.hpp | 4 ++++ 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index e6e0a750..c69533ee 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -157,15 +157,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url) { const auto HEADERSSTATUS = headersValid(); if (HEADERSSTATUS != HEADERS_OK) { - - switch (HEADERSSTATUS) { - case HEADERS_CORRUPTED: std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Headers corrupted. Please run hyprpm update to fix those.\n"; break; - case HEADERS_MISMATCHED: std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Headers version mismatch. Please run hyprpm update to fix those.\n"; break; - case HEADERS_NOT_HYPRLAND: std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " It doesn't seem you are running on hyprland.\n"; break; - case HEADERS_MISSING: std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Headers missing. Please run hyprpm update to fix those.\n"; break; - default: break; - } - + std::cerr << "\n" << headerError(HEADERSSTATUS); return false; } @@ -285,6 +277,10 @@ eHeadersErrors CPluginManager::headersValid() { if (!ifs.good()) return HEADERS_CORRUPTED; + if ((std::filesystem::exists("/usr/include/hyprland/src/version.h") && verHeader != "/usr/include/hyprland/src/version.h") || + (std::filesystem::exists("/usr/local/include/hyprland/src/version.h") && verHeader != "/usr/local/include/hyprland/src/version.h")) + return HEADERS_DUPLICATED; + std::string verHeaderContent((std::istreambuf_iterator(ifs)), (std::istreambuf_iterator())); ifs.close(); @@ -395,6 +391,8 @@ bool CPluginManager::updateHeaders() { std::cout << "\n"; + std::cerr << "\n" << headerError(HEADERSVALID); + return false; } @@ -687,4 +685,21 @@ void CPluginManager::listAllPlugins() { void CPluginManager::notify(const eNotifyIcons icon, uint32_t color, int durationMs, const std::string& message) { execAndGet("hyprctl notify " + std::to_string((int)icon) + " " + std::to_string(durationMs) + " " + std::to_string(color) + " " + message); +} + +std::string CPluginManager::headerError(const eHeadersErrors err) { + switch (err) { + case HEADERS_CORRUPTED: return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers corrupted. Please run hyprpm update to fix those.\n"; + case HEADERS_MISMATCHED: return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers version mismatch. Please run hyprpm update to fix those.\n"; + case HEADERS_NOT_HYPRLAND: return std::string{Colors::RED} + "✖" + Colors::RESET + " It doesn't seem you are running on hyprland.\n"; + case HEADERS_MISSING: return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers missing. Please run hyprpm update to fix those.\n"; + case HEADERS_DUPLICATED: { + return std::string{Colors::RED} + "✖" + Colors::RESET + " Headers duplicated!!! This is a very bad sign.\n" + + " This could be due to e.g. installing hyprland manually while a system package of hyprland is also installed.\n" + + " If the above doesn't apply, check your /usr/include and /usr/local/include directories\n and remove all the hyprland headers.\n"; + } + default: break; + } + + return std::string{Colors::RED} + "✖" + Colors::RESET + " Unknown header error. Please run hyprpm update to fix those.\n"; } \ No newline at end of file diff --git a/hyprpm/src/core/PluginManager.hpp b/hyprpm/src/core/PluginManager.hpp index dcf890d6..3c5c7c5c 100644 --- a/hyprpm/src/core/PluginManager.hpp +++ b/hyprpm/src/core/PluginManager.hpp @@ -9,6 +9,7 @@ enum eHeadersErrors { HEADERS_MISSING, HEADERS_CORRUPTED, HEADERS_MISMATCHED, + HEADERS_DUPLICATED }; enum eNotifyIcons { @@ -54,6 +55,9 @@ class CPluginManager { void notify(const eNotifyIcons icon, uint32_t color, int durationMs, const std::string& message); bool m_bVerbose = false; + + private: + std::string headerError(const eHeadersErrors err); }; inline std::unique_ptr g_pPluginManager; \ No newline at end of file From 55cb565e6de201a09bc5a7fb91a9a87448cea321 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 13 Dec 2023 13:31:36 +0200 Subject: [PATCH 382/513] Nix: expose legacyRenderer package --- flake.nix | 1 + nix/overlays.nix | 1 + 2 files changed, 2 insertions(+) diff --git a/flake.nix b/flake.nix index a6d723f2..cd9869d9 100644 --- a/flake.nix +++ b/flake.nix @@ -65,6 +65,7 @@ hyprland hyprland-unwrapped hyprland-debug + hyprland-legacy-renderer # hyprland-extras xdg-desktop-portal-hyprland # dependencies diff --git a/nix/overlays.nix b/nix/overlays.nix index 60ebd574..3658cdfd 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -38,6 +38,7 @@ in { }; hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;}; hyprland-debug = final.hyprland.override {debug = true;}; + hyprland-legacy-renderer = final.hyprland.override { legacyRenderer = true; }; hyprland-nvidia = builtins.trace '' hyprland-nvidia was removed. Please use the hyprland package. From b2e5a80e2ff1fcbf8164a45c5ef8ebffbb511fae Mon Sep 17 00:00:00 2001 From: Junxuan Liao <70618504+MikeWalrus@users.noreply.github.com> Date: Wed, 13 Dec 2023 22:15:03 +0800 Subject: [PATCH 383/513] hyprpm: Link against tomlplusplus when using cmake (#4145) This reduces the compilation time and is consistent with the meson version. --- hyprpm/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hyprpm/CMakeLists.txt b/hyprpm/CMakeLists.txt index e9cbefa1..a6bd1eca 100644 --- a/hyprpm/CMakeLists.txt +++ b/hyprpm/CMakeLists.txt @@ -9,6 +9,8 @@ file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp") set(CMAKE_CXX_STANDARD 23) -pkg_check_modules(deps REQUIRED IMPORTED_TARGET tomlplusplus) +pkg_check_modules(tomlplusplus REQUIRED IMPORTED_TARGET tomlplusplus) add_executable(hyprpm ${SRCFILES}) + +target_link_libraries(hyprpm PUBLIC PkgConfig::tomlplusplus) From 01e5c59d752d3fe7fa484330fa48e010054b8fa1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Wed, 13 Dec 2023 17:25:19 +0000 Subject: [PATCH 384/513] Revert "xwayland: push invisible windows outside layout" This reverts commit accb3d8d0b339ce83dd36704503253d874c7163b. Bad idea --- src/Compositor.cpp | 2 +- src/helpers/Monitor.cpp | 27 +-------------------------- src/managers/XWaylandManager.cpp | 4 +--- 3 files changed, 3 insertions(+), 30 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 0eb1b00a..2c7c740e 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2773,4 +2773,4 @@ void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scal void CCompositor::setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform) { wlr_surface_set_preferred_buffer_transform(pSurface, transform); -} \ No newline at end of file +} diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 0132db63..c112d07d 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -565,15 +565,6 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool g_pCompositor->updateFullscreenFadeOnWorkspace(pWorkspace); g_pConfigManager->ensureVRR(this); - - for (auto& w : g_pCompositor->m_vWindows) { - if (w->m_iWorkspaceID != POLDWORKSPACE->m_iID || !w->m_bMappedX11 || !w->m_bIsX11 || w->isHidden() || w->m_iMonitorID != ID) - continue; - - g_pXWaylandManager->moveXWaylandWindow(w.get(), {30000, 30000}); - } - - g_pCompositor->forceReportSizesToWindowsOnWorkspace(pWorkspace->m_iID); } void CMonitor::changeWorkspace(const int& id, bool internal) { @@ -585,9 +576,7 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) { if (!pWorkspace) { // remove special if exists - const auto EXISTINGSPECIAL = g_pCompositor->getWorkspaceByID(specialWorkspaceID); - - if (EXISTINGSPECIAL) { + if (const auto EXISTINGSPECIAL = g_pCompositor->getWorkspaceByID(specialWorkspaceID); EXISTINGSPECIAL) { EXISTINGSPECIAL->startAnim(false, false); g_pEventManager->postEvent(SHyprIPCEvent{"activespecial", "," + szName}); } @@ -601,18 +590,6 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) { else g_pInputManager->refocus(); - // for xwayland: yeet all the windows to narnia to avoid some focus fuckery. I hate xwayland. - // I'll avoid setting XCB_ICCCM_WM_STATE_ICONIC (aka minimized) so that the apps don't do stupid shit. - - if (EXISTINGSPECIAL) { - for (auto& w : g_pCompositor->m_vWindows) { - if (w->m_iWorkspaceID != EXISTINGSPECIAL->m_iID || !w->m_bMappedX11 || !w->m_bIsX11 || w->isHidden() || w->m_iMonitorID != ID) - continue; - - g_pXWaylandManager->moveXWaylandWindow(w.get(), {30000, 30000}); - } - } - return; } @@ -654,8 +631,6 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) { g_pEventManager->postEvent(SHyprIPCEvent{"activespecial", pWorkspace->m_szName + "," + szName}); g_pHyprRenderer->damageMonitor(this); - - g_pCompositor->forceReportSizesToWindowsOnWorkspace(specialWorkspaceID); } void CMonitor::setSpecialWorkspace(const int& id) { diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index dcb706e3..2883f205 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -262,9 +262,7 @@ void CHyprXWaylandManager::moveXWaylandWindow(CWindow* pWindow, const Vector2D& if (!pWindow->m_bIsX11) return; - Vector2D size = pWindow->m_vRealSize.goalv() * pWindow->m_fX11SurfaceScaledBy; - - wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pos.x, pos.y, size.x, size.y); + wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pos.x, pos.y, pWindow->m_vRealSize.vec().x, pWindow->m_vRealSize.vec().y); } void CHyprXWaylandManager::checkBorders(CWindow* pWindow) { From f7cde9c92cb9e7c908f18ecf10ebdb366d0832b5 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 14 Dec 2023 20:02:20 +0200 Subject: [PATCH 385/513] Nix: remove duplicate options from modules (#4012) --- flake.nix | 26 ++++--- nix/hm-module.nix | 170 ++-------------------------------------------- nix/module.nix | 92 +++---------------------- 3 files changed, 28 insertions(+), 260 deletions(-) diff --git a/flake.nix b/flake.nix index cd9869d9..6807c0f3 100644 --- a/flake.nix +++ b/flake.nix @@ -62,13 +62,16 @@ inherit (pkgsFor.${system}) # hyprland-packages + hyprland hyprland-unwrapped hyprland-debug hyprland-legacy-renderer # hyprland-extras + xdg-desktop-portal-hyprland # dependencies + hyprland-protocols wlroots-hyprland udis86 @@ -76,17 +79,18 @@ }); devShells = eachSystem (system: { - default = pkgsFor.${system}.mkShell.override { - stdenv = pkgsFor.${system}.gcc13Stdenv; - } { - name = "hyprland-shell"; - nativeBuildInputs = with pkgsFor.${system}; [cmake python3]; - buildInputs = [self.packages.${system}.wlroots-hyprland]; - inputsFrom = [ - self.packages.${system}.wlroots-hyprland - self.packages.${system}.hyprland - ]; - }; + default = + pkgsFor.${system}.mkShell.override { + stdenv = pkgsFor.${system}.gcc13Stdenv; + } { + name = "hyprland-shell"; + nativeBuildInputs = with pkgsFor.${system}; [cmake python3]; + buildInputs = [self.packages.${system}.wlroots-hyprland]; + inputsFrom = [ + self.packages.${system}.wlroots-hyprland + self.packages.${system}.hyprland + ]; + }; }); formatter = eachSystem (system: nixpkgs.legacyPackages.${system}.alejandra); diff --git a/nix/hm-module.nix b/nix/hm-module.nix index 9b065e6f..e3c788d0 100644 --- a/nix/hm-module.nix +++ b/nix/hm-module.nix @@ -4,171 +4,11 @@ self: { pkgs, ... }: let - cfg = config.wayland.windowManager.hyprland; - defaultHyprlandPackage = self.packages.${pkgs.stdenv.hostPlatform.system}.default.override { - enableXWayland = cfg.xwayland.enable; - }; + inherit (pkgs.stdenv.hostPlatform) system; + + package = self.packages.${system}.default; in { - disabledModules = ["services/window-managers/hyprland.nix"]; - - meta.maintainers = [lib.maintainers.fufexan]; - - options.wayland.windowManager.hyprland = { - enable = - lib.mkEnableOption null - // { - description = lib.mdDoc '' - Whether to enable Hyprland, the dynamic tiling Wayland compositor - that doesn't sacrifice on its looks. - - You can manually launch Hyprland by executing {command}`Hyprland` on - a TTY. - - See for more information. - ''; - }; - - package = lib.mkOption { - type = with lib.types; nullOr package; - default = defaultHyprlandPackage; - defaultText = lib.literalExpression '' - hyprland.packages.''${pkgs.stdenv.hostPlatform.system}.default.override { - enableXWayland = config.wayland.windowManager.hyprland.xwayland.enable; - } - ''; - description = lib.mdDoc '' - Hyprland package to use. Will override the 'xwayland' option. - - Defaults to the one provided by the flake. Set it to - {package}`pkgs.hyprland` to use the one provided by nixpkgs or - if you have an overlay. - - Set to null to not add any Hyprland package to your path. This should - be done if you want to use the NixOS module to install Hyprland. - ''; - }; - - plugins = lib.mkOption { - type = with lib.types; listOf (either package path); - default = []; - description = lib.mdDoc '' - List of Hyprland plugins to use. Can either be packages or - absolute plugin paths. - ''; - }; - - systemdIntegration = lib.mkOption { - type = lib.types.bool; - default = pkgs.stdenv.isLinux; - description = lib.mdDoc '' - Whether to enable {file}`hyprland-session.target` on - Hyprland startup. This links to {file}`graphical-session.target`. - Some important environment variables will be imported to systemd - and dbus user environment before reaching the target, including - - {env}`DISPLAY` - - {env}`HYPRLAND_INSTANCE_SIGNATURE` - - {env}`WAYLAND_DISPLAY` - - {env}`XDG_CURRENT_DESKTOP` - ''; - }; - - disableAutoreload = - lib.mkEnableOption null - // { - description = lib.mdDoc '' - Whether to disable automatically reloading Hyprland's configuration when - rebuilding the Home Manager profile. - ''; - }; - - xwayland.enable = lib.mkEnableOption (lib.mdDoc "XWayland") // {default = true;}; - - extraConfig = lib.mkOption { - type = lib.types.nullOr lib.types.lines; - default = ""; - description = lib.mdDoc '' - Extra configuration lines to add to {file}`~/.config/hypr/hyprland.conf`. - ''; - }; - - recommendedEnvironment = - lib.mkEnableOption null - // { - description = lib.mdDoc '' - Whether to set the recommended environment variables. - ''; - }; + config = { + wayland.windowManager.hyprland.package = lib.mkDefault package; }; - - config = lib.mkIf cfg.enable { - warnings = - if (cfg.systemdIntegration || cfg.plugins != []) && cfg.extraConfig == null - then [ - '' - You have enabled hyprland.systemdIntegration or listed plugins in hyprland.plugins. - Your Hyprland config will be linked by home manager. - Set hyprland.extraConfig or unset hyprland.systemdIntegration and hyprland.plugins to remove this warning. - '' - ] - else []; - - home.packages = - lib.optional (cfg.package != null) cfg.package - ++ lib.optional cfg.xwayland.enable pkgs.xwayland; - - home.sessionVariables = - lib.mkIf cfg.recommendedEnvironment {NIXOS_OZONE_WL = "1";}; - - xdg.configFile."hypr/hyprland.conf" = lib.mkIf (cfg.systemdIntegration || cfg.extraConfig != null || cfg.plugins != []) { - text = - (lib.optionalString cfg.systemdIntegration '' - exec-once=${pkgs.dbus}/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP && systemctl --user start hyprland-session.target - '') - + lib.concatStrings (builtins.map (entry: let - plugin = - if lib.types.package.check entry - then "${entry}/lib/lib${entry.pname}.so" - else entry; - in "plugin = ${plugin}\n") - cfg.plugins) - + ( - if cfg.extraConfig != null - then cfg.extraConfig - else "" - ); - - onChange = let - hyprlandPackage = - if cfg.package == null - then defaultHyprlandPackage - else cfg.package; - in - lib.mkIf (!cfg.disableAutoreload) '' - ( # execute in subshell so that `shopt` won't affect other scripts - shopt -s nullglob # so that nothing is done if /tmp/hypr/ does not exist or is empty - for instance in /tmp/hypr/*; do - HYPRLAND_INSTANCE_SIGNATURE=''${instance##*/} ${hyprlandPackage}/bin/hyprctl reload config-only \ - || true # ignore dead instance(s) - done - ) - ''; - }; - - systemd.user.targets.hyprland-session = lib.mkIf cfg.systemdIntegration { - Unit = { - Description = "Hyprland compositor session"; - Documentation = ["man:systemd.special(7)"]; - BindsTo = ["graphical-session.target"]; - Wants = ["graphical-session-pre.target"]; - After = ["graphical-session-pre.target"]; - }; - }; - }; - - imports = [ - (lib.mkRemovedOptionModule ["wayland" "windowManager" "hyprland" "xwayland" "hidpi"] - "Support for this option has been removed. Refer to https://wiki.hyprland.org/Configuring/XWayland for more info") - (lib.mkRemovedOptionModule ["wayland" "windowManager" "hyprland" "xwayland" "enableNvidiaPatches"] - "Nvidia patches are no longer needed for Hyprland") - ]; } diff --git a/nix/module.nix b/nix/module.nix index 1f1d2585..6f553893 100644 --- a/nix/module.nix +++ b/nix/module.nix @@ -2,96 +2,20 @@ inputs: { config, lib, pkgs, - options, ... -}: -with lib; let - cfg = config.programs.hyprland; +}: let inherit (pkgs.stdenv.hostPlatform) system; + cfg = config.programs.hyprland; - finalPortalPackage = cfg.portalPackage.override { + package = inputs.self.packages.${system}.hyprland; + portalPackage = inputs.self.packages.${system}.xdg-desktop-portal-hyprland.override { hyprland = cfg.finalPackage; }; in { - # disables Nixpkgs Hyprland module to avoid conflicts - disabledModules = ["programs/hyprland.nix"]; - - options.programs.hyprland = { - enable = - mkEnableOption null - // { - description = mdDoc '' - Hyprland, the dynamic tiling Wayland compositor that doesn't sacrifice on its looks. - - You can manually launch Hyprland by executing {command}`Hyprland` on a TTY. - - A configuration file will be generated in {file}`~/.config/hypr/hyprland.conf`. - See for more information. - ''; - }; - - package = mkPackageOptionMD inputs.self.packages.${system} "hyprland" { }; - - finalPackage = mkOption { - type = types.package; - readOnly = true; - default = cfg.package.override { - enableXWayland = cfg.xwayland.enable; - }; - defaultText = - literalExpression - "`programs.hyprland.package` with applied configuration"; - description = mdDoc '' - The Hyprland package after applying configuration. - ''; - }; - - portalPackage = mkPackageOptionMD inputs.xdph.packages.${system} "xdg-desktop-portal-hyprland" {}; - - xwayland.enable = mkEnableOption (mdDoc "support for XWayland") // {default = true;}; - }; - - config = mkIf cfg.enable { - environment.systemPackages = [cfg.finalPackage]; - - # NixOS changed the name of this attribute between NixOS 23.05 and - # 23.11 - fonts = if builtins.hasAttr "enableDefaultPackages" options.fonts - then {enableDefaultPackages = mkDefault true;} - else {enableDefaultFonts = mkDefault true;}; - - hardware.opengl.enable = mkDefault true; - - programs = { - dconf.enable = mkDefault true; - xwayland.enable = mkDefault cfg.xwayland.enable; - }; - - security.polkit.enable = true; - - services.xserver.displayManager.sessionPackages = [cfg.finalPackage]; - - xdg.portal = { - enable = mkDefault true; - extraPortals = [finalPortalPackage]; + config = { + programs.hyprland = { + package = lib.mkDefault package; + portalPackage = lib.mkDefault portalPackage; }; }; - - imports = with lib; [ - ( - mkRemovedOptionModule - ["programs" "hyprland" "xwayland" "hidpi"] - "XWayland patches are deprecated. Refer to https://wiki.hyprland.org/Configuring/XWayland" - ) - ( - mkRemovedOptionModule - ["programs" "hyprland" "enableNvidiaPatches"] - "Nvidia patches are no longer needed" - ) - ( - mkRemovedOptionModule - ["programs" "hyprland" "nvidiaPatches"] - "Nvidia patches are no longer needed" - ) - ]; } From 36fa33f7ca2f555cc8581a13c5899effed2bf84b Mon Sep 17 00:00:00 2001 From: dranull <150595692+dranull@users.noreply.github.com> Date: Fri, 15 Dec 2023 00:39:03 +0000 Subject: [PATCH 386/513] input: Prevent crash with invalid keyboard layout (#4157) --- src/managers/input/InputManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 8b4b51bc..9df59dfb 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -933,7 +933,8 @@ void CInputManager::applyConfigToKeyboard(SKeyboard* pKeyboard) { g_pEventManager->postEvent(SHyprIPCEvent{"activelayout", pKeyboard->name + "," + LAYOUTSTR}); EMIT_HOOK_EVENT("activeLayout", (std::vector{pKeyboard, (void*)&LAYOUTSTR})); - Debug::log(LOG, "Set the keyboard layout to {} and variant to {} for keyboard \"{}\"", rules.layout, rules.variant, pKeyboard->keyboard->name); + Debug::log(LOG, "Set the keyboard layout to {} and variant to {} for keyboard \"{}\"", pKeyboard->currentRules.layout, pKeyboard->currentRules.variant, + pKeyboard->keyboard->name); } void CInputManager::newMouse(wlr_input_device* mouse, bool virt) { From 395ab3ba370f5e12fcba594232c338c16deef0ed Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 15 Dec 2023 15:38:08 +0000 Subject: [PATCH 387/513] xdg: use better min/max size checks for floating resizes --- src/events/Windows.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index efefcbec..390fb1e1 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -814,22 +814,29 @@ void Events::listener_commitWindow(void* owner, void* data) { if (PWINDOW->m_bIsX11 || !PWINDOW->m_bIsFloating || PWINDOW->m_bIsFullscreen) return; - const auto ISRIGID = PWINDOW->m_uSurface.xdg->toplevel->current.max_height == PWINDOW->m_uSurface.xdg->toplevel->current.min_height && - PWINDOW->m_uSurface.xdg->toplevel->current.max_width == PWINDOW->m_uSurface.xdg->toplevel->current.min_width; + const auto MINSIZE = Vector2D{PWINDOW->m_uSurface.xdg->toplevel->current.min_width, PWINDOW->m_uSurface.xdg->toplevel->current.min_height}; + const auto MAXSIZE = Vector2D{PWINDOW->m_uSurface.xdg->toplevel->current.max_width, PWINDOW->m_uSurface.xdg->toplevel->current.max_height}; - if (!ISRIGID) + if (MAXSIZE < Vector2D{1, 1}) return; - const Vector2D REQUESTEDSIZE = {PWINDOW->m_uSurface.xdg->toplevel->current.max_width, PWINDOW->m_uSurface.xdg->toplevel->current.max_height}; + const auto REALSIZE = PWINDOW->m_vRealSize.goalv(); + Vector2D newSize = REALSIZE; - if (REQUESTEDSIZE == PWINDOW->m_vReportedSize || REQUESTEDSIZE.x < 5 || REQUESTEDSIZE.y < 5) - return; + if (MAXSIZE.x < newSize.x) + newSize.x = MAXSIZE.x; + if (MAXSIZE.y < newSize.y) + newSize.y = MAXSIZE.y; + if (MINSIZE.x > newSize.x) + newSize.x = MINSIZE.x; + if (MINSIZE.y > newSize.y) + newSize.y = MINSIZE.y; - const Vector2D DELTA = PWINDOW->m_vReportedSize - REQUESTEDSIZE; + const Vector2D DELTA = REALSIZE - newSize; PWINDOW->m_vRealPosition = PWINDOW->m_vRealPosition.goalv() + DELTA / 2.0; - PWINDOW->m_vRealSize = REQUESTEDSIZE; - g_pXWaylandManager->setWindowSize(PWINDOW, REQUESTEDSIZE, true); + PWINDOW->m_vRealSize = newSize; + g_pXWaylandManager->setWindowSize(PWINDOW, newSize, true); g_pHyprRenderer->damageWindow(PWINDOW); } From 79d8d14fe08fed39e9796a76fcb9833c6b64b1c0 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 15 Dec 2023 18:27:04 +0000 Subject: [PATCH 388/513] config: add qt env to default config --- example/hyprland.conf | 2 ++ src/config/defaultConfig.hpp | 1 + 2 files changed, 3 insertions(+) diff --git a/example/hyprland.conf b/example/hyprland.conf index e6c2a641..62b6e6e5 100644 --- a/example/hyprland.conf +++ b/example/hyprland.conf @@ -23,8 +23,10 @@ monitor=,preferred,auto,auto $terminal = kitty $fileManager = dolphin $menu = wofi --show drun + # Some default env vars. env = XCURSOR_SIZE,24 +env = QT_QPA_PLATFORMTHEME,qt5ct # change to qt6ct if you have that # For all categories, see https://wiki.hyprland.org/Configuring/Variables/ input { diff --git a/src/config/defaultConfig.hpp b/src/config/defaultConfig.hpp index 22d3b332..1e149a7a 100644 --- a/src/config/defaultConfig.hpp +++ b/src/config/defaultConfig.hpp @@ -35,6 +35,7 @@ $menu = wofi --show drun # Some default env vars. env = XCURSOR_SIZE,24 +env = QT_QPA_PLATFORMTHEME,qt5ct # change to qt6ct if you have that # For all categories, see https://wiki.hyprland.org/Configuring/Variables/ input { From e1ed8e11cadc35080edc4b5b6add94f2b6c15a8f Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 15 Dec 2023 20:59:13 +0000 Subject: [PATCH 389/513] internal: import qt env to dbus --- src/Compositor.cpp | 10 +++++----- src/config/ConfigManager.cpp | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 2c7c740e..4f80100a 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -518,13 +518,13 @@ void CCompositor::startCompositor() { signal(SIGPIPE, SIG_IGN); if (m_sWLRSession /* Session-less Hyprland usually means a nest, don't update the env in that case */ && fork() == 0) - execl( - "/bin/sh", "/bin/sh", "-c", + execl("/bin/sh", "/bin/sh", "-c", #ifdef USES_SYSTEMD - "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP && hash dbus-update-activation-environment 2>/dev/null && " + "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME && hash " + "dbus-update-activation-environment 2>/dev/null && " #endif - "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE", - nullptr); + "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE QT_QPA_PLATFORMTHEME", + nullptr); Debug::log(LOG, "Running on WAYLAND_DISPLAY: {}", m_szWLDisplaySocket); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 75def1dd..8afa627d 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2092,12 +2092,12 @@ void CConfigManager::dispatchExecOnce() { // update dbus env if (g_pCompositor->m_sWLRSession) - handleRawExec( - "", + handleRawExec("", #ifdef USES_SYSTEMD - "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP && hash dbus-update-activation-environment 2>/dev/null && " + "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME && hash " + "dbus-update-activation-environment 2>/dev/null && " #endif - "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE"); + "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE QT_QPA_PLATFORMTHEME"); firstExecDispatched = true; From 4e5d9b90c0521f1e0815ea35c4f2c939791c5dd6 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 15 Dec 2023 21:04:34 +0000 Subject: [PATCH 390/513] toplevelexport: fix missing GL_READ_FRAMEBUFFER set in shm copy ref #4165 --- src/protocols/ToplevelExport.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 3c80eb18..e0e618c5 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -400,6 +400,10 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times outFB.bind(); +#ifndef GLES2 + glBindFramebuffer(GL_READ_FRAMEBUFFER, outFB.m_iFb); +#endif + glPixelStorei(GL_PACK_ALIGNMENT, 1); glReadPixels(0, 0, frame->box.width, frame->box.height, PFORMAT->glFormat, PFORMAT->glType, data); From b1b8d732e64ecf527baef010ad2f28ed3b8c4ac1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 15 Dec 2023 21:20:13 +0000 Subject: [PATCH 391/513] toplevelexport: fix missed pmonitor set for opengl ref #4165 --- src/protocols/ToplevelExport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index e0e618c5..425572eb 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -397,7 +397,7 @@ bool CToplevelExportProtocolManager::copyFrameShm(SScreencopyFrame* frame, times g_pHyprRenderer->endRender(); g_pHyprRenderer->makeEGLCurrent(); - + g_pHyprOpenGL->m_RenderData.pMonitor = PMONITOR; outFB.bind(); #ifndef GLES2 From 9ca0c7d814d6039450ff0341556faa1ce9b37e82 Mon Sep 17 00:00:00 2001 From: dranull <150595692+dranull@users.noreply.github.com> Date: Sat, 16 Dec 2023 20:47:58 +0000 Subject: [PATCH 392/513] input: Activate resize_on_border only when key is pressed (#4170) --- src/managers/input/InputManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 9df59dfb..c6904a82 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -625,7 +625,7 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { // clicking on border triggers resize // TODO detect click on LS properly - if (*PRESIZEONBORDER && !m_bLastFocusOnLS) { + if (*PRESIZEONBORDER && !m_bLastFocusOnLS && e->state == WLR_BUTTON_PRESSED) { if (w && !w->m_bIsFullscreen) { const CBox real = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; const CBox grab = {real.x - BORDER_GRAB_AREA, real.y - BORDER_GRAB_AREA, real.width + 2 * BORDER_GRAB_AREA, real.height + 2 * BORDER_GRAB_AREA}; From 2a777cb71bc727836ca9c73ebb193773a99f8f1e Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Sun, 17 Dec 2023 14:29:58 +0000 Subject: [PATCH 393/513] hyprctl: add commit date to "hyprctl version" (#4171) * add commit date to "hyprctl version" modified: scripts/generateVersion.sh modified: src/debug/HyprCtl.cpp modified: src/version.h.in * Nix: add date to hyprctl --------- Co-authored-by: Mihai Fufezan --- nix/default.nix | 3 ++- nix/overlays.nix | 9 ++++++--- scripts/generateVersion.sh | 4 +++- src/debug/HyprCtl.cpp | 5 +++-- src/version.h.in | 3 ++- 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/nix/default.nix b/nix/default.nix index d80a42a9..4b1be0e2 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -1,6 +1,5 @@ { lib, - fetchurl, stdenv, pkg-config, makeWrapper, @@ -35,6 +34,7 @@ wrapRuntimeDeps ? true, version ? "git", commit, + date, # deprecated flags enableNvidiaPatches ? false, nvidiaPatches ? false, @@ -119,6 +119,7 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov --replace "@HASH@" '${commit}' \ --replace "@BRANCH@" "" \ --replace "@MESSAGE@" "" \ + --replace "@DATE@" "${date}" \ --replace "@TAG@" "" \ --replace "@DIRTY@" '${ if commit == "" diff --git a/nix/overlays.nix b/nix/overlays.nix index 3658cdfd..5eb7b082 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -28,17 +28,20 @@ in { self.overlays.wlroots-hyprland self.overlays.udis86 # Hyprland packages themselves - (final: prev: { + (final: prev: let + date = mkDate (self.lastModifiedDate or "19700101"); + in { hyprland = final.callPackage ./default.nix { stdenv = final.gcc13Stdenv; - version = "${props.version}+date=${mkDate (self.lastModifiedDate or "19700101")}_${self.shortRev or "dirty"}"; + version = "${props.version}+date=${date}_${self.shortRev or "dirty"}"; wlroots = final.wlroots-hyprland; commit = self.rev or ""; inherit (final) udis86 hyprland-protocols; + inherit date; }; hyprland-unwrapped = final.hyprland.override {wrapRuntimeDeps = false;}; hyprland-debug = final.hyprland.override {debug = true;}; - hyprland-legacy-renderer = final.hyprland.override { legacyRenderer = true; }; + hyprland-legacy-renderer = final.hyprland.override {legacyRenderer = true;}; hyprland-nvidia = builtins.trace '' hyprland-nvidia was removed. Please use the hyprland package. diff --git a/scripts/generateVersion.sh b/scripts/generateVersion.sh index c54e2ebd..443c5c54 100755 --- a/scripts/generateVersion.sh +++ b/scripts/generateVersion.sh @@ -4,11 +4,13 @@ cp -fr ./src/version.h.in ./src/version.h HASH=$(git rev-parse HEAD) BRANCH=$(git rev-parse --abbrev-ref HEAD) MESSAGE=$(git show ${GIT_COMMIT_HASH} | head -n 5 | tail -n 1 | sed -e 's/#//g' -e 's/\"//g') +DATE=$(git show ${GIT_COMMIT_HASH} --no-patch --format=%cd --date=local) DIRTY=$(git diff-index --quiet HEAD -- || echo dirty) TAG=$(git describe --tags) sed -i -e "s#@HASH@#${HASH}#" ./src/version.h sed -i -e "s#@BRANCH@#${BRANCH}#" ./src/version.h sed -i -e "s#@MESSAGE@#${MESSAGE}#" ./src/version.h +sed -i -e "s#@DATE@#${DATE}#" ./src/version.h sed -i -e "s#@DIRTY@#${DIRTY}#" ./src/version.h -sed -i -e "s#@TAG@#${TAG}#" ./src/version.h \ No newline at end of file +sed -i -e "s#@TAG@#${TAG}#" ./src/version.h diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 98526ef4..68b74fa7 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -748,7 +748,7 @@ std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) { if (format == HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL) { std::string result = "Hyprland, built from branch " + std::string(GIT_BRANCH) + " at commit " + GIT_COMMIT_HASH + " " + GIT_DIRTY + " (" + commitMsg + - ").\nTag: " + GIT_TAG + "\n\nflags: (if any)\n"; + ").\nDate: " + GIT_COMMIT_DATE + "\nTag: " + GIT_TAG + "\n\nflags: (if any)\n"; #ifdef LEGACY_RENDERER result += "legacyrenderer\n"; @@ -771,9 +771,10 @@ std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) { "commit": "{}", "dirty": {}, "commit_message": "{}", + "commit_date": "{}", "tag": "{}", "flags": [)#", - GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_TAG); + GIT_BRANCH, GIT_COMMIT_HASH, (strcmp(GIT_DIRTY, "dirty") == 0 ? "true" : "false"), escapeJSONStrings(commitMsg), GIT_COMMIT_DATE, GIT_TAG); #ifdef LEGACY_RENDERER result += "\"legacyrenderer\","; diff --git a/src/version.h.in b/src/version.h.in index 6bfd14e5..e0dd8a83 100644 --- a/src/version.h.in +++ b/src/version.h.in @@ -2,5 +2,6 @@ #define GIT_COMMIT_HASH "@HASH@" #define GIT_BRANCH "@BRANCH@" #define GIT_COMMIT_MESSAGE "@MESSAGE@" +#define GIT_COMMIT_DATE "@DATE@" #define GIT_DIRTY "@DIRTY@" -#define GIT_TAG "@TAG@" \ No newline at end of file +#define GIT_TAG "@TAG@" From c0d9dcc586ab17bf67c48c02a08bca28727f9237 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 17 Dec 2023 14:53:48 +0000 Subject: [PATCH 394/513] xwayland: set reported and pending size/pos on geometry sets --- src/events/Windows.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 390fb1e1..b184f4c2 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -1030,7 +1030,8 @@ void Events::listener_configureX11(void* owner, void* data) { if (!PWINDOW->m_uSurface.xwayland->surface || !PWINDOW->m_uSurface.xwayland->surface->mapped || !PWINDOW->m_bMappedX11) { wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height); - PWINDOW->m_vReportedSize = {E->width, E->height}; + PWINDOW->m_vPendingReportedSize = {E->width, E->height}; + PWINDOW->m_vReportedSize = {E->width, E->height}; return; } @@ -1067,7 +1068,8 @@ void Events::listener_configureX11(void* owner, void* data) { wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height); - PWINDOW->m_vReportedSize = {E->width, E->height}; + PWINDOW->m_vPendingReportedSize = {E->width, E->height}; + PWINDOW->m_vReportedSize = {E->width, E->height}; PWINDOW->updateWindowDecos(); @@ -1137,6 +1139,10 @@ void Events::listener_unmanagedSetGeometry(void* owner, void* data) { g_pCompositor->changeWindowZOrder(PWINDOW, true); PWINDOW->updateWindowDecos(); g_pHyprRenderer->damageWindow(PWINDOW); + + PWINDOW->m_vReportedPosition = PWINDOW->m_vRealPosition.goalv(); + PWINDOW->m_vReportedSize = PWINDOW->m_vRealSize.goalv(); + PWINDOW->m_vPendingReportedSize = PWINDOW->m_vReportedSize; } } From 8c9f38e40500720d4de5881d62ec43625e9680ea Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 17 Dec 2023 19:58:01 +0000 Subject: [PATCH 395/513] events: improve wl_surface::commit event tracking --- src/events/Windows.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index b184f4c2..6a151cfd 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -479,7 +479,6 @@ void Events::listener_mapWindow(void* owner, void* data) { Debug::log(LOG, "Window got assigned a surfaceTreeNode {:x}", (uintptr_t)PWINDOW->m_pSurfaceTree); if (!PWINDOW->m_bIsX11) { - PWINDOW->hyprListener_commitWindow.initCallback(&PWINDOW->m_uSurface.xdg->surface->events.commit, &Events::listener_commitWindow, PWINDOW, "XDG Window Late"); PWINDOW->hyprListener_setTitleWindow.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.set_title, &Events::listener_setTitleWindow, PWINDOW, "XDG Window Late"); PWINDOW->hyprListener_newPopupXDG.initCallback(&PWINDOW->m_uSurface.xdg->events.new_popup, &Events::listener_newPopupXDG, PWINDOW, "XDG Window Late"); PWINDOW->hyprListener_requestMaximize.initCallback(&PWINDOW->m_uSurface.xdg->toplevel->events.request_maximize, &Events::listener_requestMaximize, PWINDOW, @@ -672,7 +671,6 @@ void Events::listener_unmapWindow(void* owner, void* data) { if (!PWINDOW->m_bIsX11) { Debug::log(LOG, "Unregistered late callbacks XDG"); - PWINDOW->hyprListener_commitWindow.removeCallback(); PWINDOW->hyprListener_setTitleWindow.removeCallback(); PWINDOW->hyprListener_newPopupXDG.removeCallback(); PWINDOW->hyprListener_requestMaximize.removeCallback(); @@ -853,6 +851,7 @@ void Events::listener_destroyWindow(void* owner, void* data) { g_pCompositor->m_pLastFocus = nullptr; } + PWINDOW->hyprListener_commitWindow.removeCallback(); PWINDOW->hyprListener_mapWindow.removeCallback(); PWINDOW->hyprListener_unmapWindow.removeCallback(); PWINDOW->hyprListener_destroyWindow.removeCallback(); @@ -1186,6 +1185,7 @@ void Events::listener_surfaceXWayland(wl_listener* listener, void* data) { PNEWWINDOW->hyprListener_destroyWindow.initCallback(&XWSURFACE->events.destroy, &Events::listener_destroyWindow, PNEWWINDOW, "XWayland Window"); PNEWWINDOW->hyprListener_setOverrideRedirect.initCallback(&XWSURFACE->events.set_override_redirect, &Events::listener_setOverrideRedirect, PNEWWINDOW, "XWayland Window"); PNEWWINDOW->hyprListener_configureX11.initCallback(&XWSURFACE->events.request_configure, &Events::listener_configureX11, PNEWWINDOW, "XWayland Window"); + PNEWWINDOW->hyprListener_commitWindow.initCallback(&XWSURFACE->surface->events.commit, &Events::listener_commitWindow, PNEWWINDOW, "XWayland Window"); } void Events::listener_newXDGToplevel(wl_listener* listener, void* data) { @@ -1200,6 +1200,7 @@ void Events::listener_newXDGToplevel(wl_listener* listener, void* data) { PNEWWINDOW->hyprListener_mapWindow.initCallback(&XDGSURFACE->surface->events.map, &Events::listener_mapWindow, PNEWWINDOW, "XDG Window"); PNEWWINDOW->hyprListener_destroyWindow.initCallback(&XDGSURFACE->events.destroy, &Events::listener_destroyWindow, PNEWWINDOW, "XDG Window"); + PNEWWINDOW->hyprListener_commitWindow.initCallback(&XDGSURFACE->surface->events.commit, &Events::listener_commitWindow, PNEWWINDOW, "XDG Window"); } void Events::listener_NewXDGDeco(wl_listener* listener, void* data) { From bf7374011b17776137c6cadb016695ef05926c6c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 17 Dec 2023 19:58:11 +0000 Subject: [PATCH 396/513] xwaylandmgr: allow resizes without a monitor --- src/managers/XWaylandManager.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index 2883f205..c384e6cc 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -150,14 +150,12 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f static auto* const PXWLFORCESCALEZERO = &g_pConfigManager->getConfigValuePtr("xwayland:force_zero_scaling")->intValue; const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); - if (!PMONITOR) - return; // calculate pos // TODO: this should be decoupled from setWindowSize IMO Vector2D windowPos = pWindow->m_vRealPosition.vec(); - if (pWindow->m_bIsX11) { + if (pWindow->m_bIsX11 && PMONITOR) { windowPos = windowPos - PMONITOR->vecPosition; // normalize to monitor if (*PXWLFORCESCALEZERO) windowPos = windowPos * PMONITOR->scale; // scale if applicable @@ -172,11 +170,9 @@ void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, Vector2D size, bool f pWindow->m_fX11SurfaceScaledBy = 1.f; - if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11) { - if (const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); PMONITOR) { - size = size * PMONITOR->scale; - pWindow->m_fX11SurfaceScaledBy = PMONITOR->scale; - } + if (*PXWLFORCESCALEZERO && pWindow->m_bIsX11 && PMONITOR) { + size = size * PMONITOR->scale; + pWindow->m_fX11SurfaceScaledBy = PMONITOR->scale; } if (pWindow->m_bIsX11) From 9fd928e114d7f57ac03aa7430d9cba41843347de Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 17 Dec 2023 20:00:18 +0000 Subject: [PATCH 397/513] internal: nuke CWindow::m_bMappedX11 it's useless. m_bIsMapped is the same. --- src/Compositor.cpp | 9 +++------ src/Window.cpp | 4 ++-- src/Window.hpp | 1 - src/events/Windows.cpp | 13 +++++-------- src/layout/DwindleLayout.cpp | 2 +- src/layout/MasterLayout.cpp | 2 +- src/managers/XWaylandManager.cpp | 2 +- 7 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 4f80100a..cbdfa288 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1065,9 +1065,6 @@ bool CCompositor::windowValidMapped(CWindow* pWindow) { if (!windowExists(pWindow)) return false; - if (pWindow->m_bIsX11 && !pWindow->m_bMappedX11) - return false; - if (!pWindow->m_bIsMapped) return false; @@ -1131,7 +1128,7 @@ SIMEPopup* CCompositor::vectorToIMEPopup(const Vector2D& pos, std::listm_bIsMapped || w->m_bFadingOut || !w->m_bMappedX11) + if (!w->m_bIsMapped || w->m_bFadingOut) continue; if (w->m_pWLSurface.wlr() == pSurface) @@ -1374,7 +1371,7 @@ void CCompositor::changeWindowZOrder(CWindow* pWindow, bool top) { toMove.emplace_front(pw); for (auto& w : m_vWindows) { - if (w->m_bIsMapped && w->m_bMappedX11 && !w->isHidden() && w->m_bIsX11 && w->X11TransientFor() == pw) { + if (w->m_bIsMapped && !w->isHidden() && w->m_bIsX11 && w->X11TransientFor() == pw) { x11Stack(w.get(), top, x11Stack); } } @@ -1729,7 +1726,7 @@ CWindow* CCompositor::getConstraintWindow(SMouse* pMouse) { const auto PSURFACE = pMouse->currentConstraint->surface; for (auto& w : m_vWindows) { - if (w->isHidden() || !w->m_bMappedX11 || !w->m_bIsMapped || !w->m_pWLSurface.exists()) + if (w->isHidden() || !w->m_bIsMapped || !w->m_pWLSurface.exists()) continue; if (w->m_bIsX11) { diff --git a/src/Window.cpp b/src/Window.cpp index bd51f2ff..da0912ee 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -231,7 +231,7 @@ pid_t CWindow::getPID() { wl_client_get_credentials(wl_resource_get_client(m_uSurface.xdg->resource), &PID, nullptr, nullptr); } else { - if (!m_bIsMapped || !m_bMappedX11) + if (!m_bIsMapped) return -1; PID = m_uSurface.xwayland->pid; @@ -322,7 +322,7 @@ void sendLeaveIter(wlr_surface* pSurface, int x, int y, void* data) { } void CWindow::updateSurfaceOutputs() { - if (m_iLastSurfaceMonitorID == m_iMonitorID || !m_bIsMapped || m_bHidden || !m_bMappedX11) + if (m_iLastSurfaceMonitorID == m_iMonitorID || !m_bIsMapped || m_bHidden) return; const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(m_iLastSurfaceMonitorID); diff --git a/src/Window.hpp b/src/Window.hpp index c4f2a15d..cff26052 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -238,7 +238,6 @@ class CWindow { // XWayland stuff bool m_bIsX11 = false; - bool m_bMappedX11 = false; CWindow* m_pX11Parent = nullptr; uint64_t m_iX11Type = 0; bool m_bIsModal = false; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 6a151cfd..7f7c8ee6 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -52,7 +52,6 @@ void Events::listener_mapWindow(void* owner, void* data) { const auto PWORKSPACE = PMONITOR->specialWorkspaceID ? g_pCompositor->getWorkspaceByID(PMONITOR->specialWorkspaceID) : g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace); PWINDOW->m_iMonitorID = PMONITOR->ID; - PWINDOW->m_bMappedX11 = true; PWINDOW->m_iWorkspaceID = PMONITOR->specialWorkspaceID ? PMONITOR->specialWorkspaceID : PMONITOR->activeWorkspace; PWINDOW->m_bIsMapped = true; PWINDOW->m_bReadyToDelete = false; @@ -712,8 +711,6 @@ void Events::listener_unmapWindow(void* owner, void* data) { g_pInputManager->releaseAllMouseButtons(); } - PWINDOW->m_bMappedX11 = false; - // remove the fullscreen window status from workspace if we closed it const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID); @@ -794,7 +791,7 @@ void Events::listener_ackConfigure(void* owner, void* data) { void Events::listener_commitWindow(void* owner, void* data) { CWindow* PWINDOW = (CWindow*)owner; - if (!PWINDOW->m_bMappedX11 || PWINDOW->isHidden() || (PWINDOW->m_bIsX11 && !PWINDOW->m_bMappedX11)) + if (!PWINDOW->m_bIsMapped || PWINDOW->isHidden()) return; if (PWINDOW->m_bIsX11) @@ -1027,7 +1024,7 @@ void Events::listener_configureX11(void* owner, void* data) { const auto E = (wlr_xwayland_surface_configure_event*)data; - if (!PWINDOW->m_uSurface.xwayland->surface || !PWINDOW->m_uSurface.xwayland->surface->mapped || !PWINDOW->m_bMappedX11) { + if (!PWINDOW->m_uSurface.xwayland->surface || !PWINDOW->m_uSurface.xwayland->surface->mapped || !PWINDOW->m_bIsMapped) { wlr_xwayland_surface_configure(PWINDOW->m_uSurface.xwayland, E->x, E->y, E->width, E->height); PWINDOW->m_vPendingReportedSize = {E->width, E->height}; PWINDOW->m_vReportedSize = {E->width, E->height}; @@ -1090,7 +1087,7 @@ void Events::listener_configureX11(void* owner, void* data) { void Events::listener_unmanagedSetGeometry(void* owner, void* data) { CWindow* PWINDOW = (CWindow*)owner; - if (!PWINDOW->m_bMappedX11) + if (!PWINDOW->m_bIsMapped) return; const auto POS = PWINDOW->m_vRealPosition.goalv(); @@ -1223,7 +1220,7 @@ void Events::listener_requestMaximize(void* owner, void* data) { wlr_xdg_surface_schedule_configure(PWINDOW->m_uSurface.xdg); } else { - if (!PWINDOW->m_bMappedX11 || PWINDOW->m_iX11Type != 1) + if (!PWINDOW->m_bIsMapped || PWINDOW->m_iX11Type != 1) return; g_pCompositor->setWindowFullscreen(PWINDOW, !PWINDOW->m_bIsFullscreen, FULLSCREEN_MAXIMIZED); @@ -1236,7 +1233,7 @@ void Events::listener_requestMinimize(void* owner, void* data) { Debug::log(LOG, "Minimize request for {}", PWINDOW); if (PWINDOW->m_bIsX11) { - if (!PWINDOW->m_bMappedX11 || PWINDOW->m_iX11Type != 1) + if (!PWINDOW->m_bIsMapped || PWINDOW->m_iX11Type != 1) return; const auto E = (wlr_xwayland_minimize_event*)data; diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index c1009a47..b30d0fb6 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -1044,7 +1044,7 @@ std::string CHyprDwindleLayout::getLayoutName() { void CHyprDwindleLayout::onEnable() { for (auto& w : g_pCompositor->m_vWindows) { - if (w->m_bIsFloating || !w->m_bMappedX11 || !w->m_bIsMapped || w->isHidden()) + if (w->m_bIsFloating || !w->m_bIsMapped || w->isHidden()) continue; onWindowCreatedTiling(w.get()); diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index ff7f9e2e..086bcdac 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -1407,7 +1407,7 @@ void CHyprMasterLayout::replaceWindowDataWith(CWindow* from, CWindow* to) { void CHyprMasterLayout::onEnable() { for (auto& w : g_pCompositor->m_vWindows) { - if (w->m_bIsFloating || !w->m_bMappedX11 || !w->m_bIsMapped || w->isHidden()) + if (w->m_bIsFloating || !w->m_bIsMapped || w->isHidden()) continue; onWindowCreatedTiling(w.get()); diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp index c384e6cc..63b8cca0 100644 --- a/src/managers/XWaylandManager.cpp +++ b/src/managers/XWaylandManager.cpp @@ -119,7 +119,7 @@ std::string CHyprXWaylandManager::getTitle(CWindow* pWindow) { } std::string CHyprXWaylandManager::getAppIDClass(CWindow* pWindow) { - if (!pWindow->m_bMappedX11 || !pWindow->m_bIsMapped) + if (!pWindow->m_bIsMapped) return ""; try { From 763d5fa05f7d0191182a1d6cd827415a65293f99 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 17 Dec 2023 20:09:34 +0000 Subject: [PATCH 398/513] xdgshell: set predicted tiled windows to monitor res size pre-map Should improve #4022 although not exactly fix. Fixing would require more witchcraft --- src/Window.hpp | 3 ++- src/events/Windows.cpp | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/Window.hpp b/src/Window.hpp index cff26052..fcd40ba6 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -229,7 +229,8 @@ class CWindow { std::string m_szInitialClass = ""; int m_iWorkspaceID = -1; - bool m_bIsMapped = false; + bool m_bIsMapped = false; + bool m_bInitialCommitPassed = false; bool m_bRequestsFloat = false; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 7f7c8ee6..699d72a1 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -791,7 +791,42 @@ void Events::listener_ackConfigure(void* owner, void* data) { void Events::listener_commitWindow(void* owner, void* data) { CWindow* PWINDOW = (CWindow*)owner; - if (!PWINDOW->m_bIsMapped || PWINDOW->isHidden()) + if (!PWINDOW->m_bIsMapped) { + + // dupes shouldn't happen, but you never know, really. + if (PWINDOW->m_bInitialCommitPassed || PWINDOW->m_bIsX11) + return; + + PWINDOW->m_bInitialCommitPassed = true; + + // this is an initial commit of a surface + // in here, the surface will ask us what size we'd like it to be. + // wlroots by default doesn't send anything, so the app can use its preferred floating size + // if we predict it will be tiled, it's better to set it to the monitor size + // so it doesn't appear with the wrong size at the beginning. + // too big > too small, because will be clipped and won't look that bad. + + auto willFloat = g_pXWaylandManager->shouldBeFloated(PWINDOW); + const auto WRULES = g_pConfigManager->getMatchingRules(PWINDOW); + for (auto& r : WRULES) { + if (r.szRule == "float") { + willFloat = true; + break; + } else if (r.szRule == "tile") { + willFloat = false; + break; + } + } + + if (willFloat) + return; + + g_pXWaylandManager->setWindowSize(PWINDOW, g_pCompositor->m_pLastMonitor ? g_pCompositor->m_pLastMonitor->vecSize : Vector2D{1920, 1080}, true); + + return; + } + + if (PWINDOW->isHidden()) return; if (PWINDOW->m_bIsX11) From 403fd7d9f6b160dec71456c9fb195a4199134eff Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 18 Dec 2023 00:15:30 +0000 Subject: [PATCH 399/513] xwayland: move commit handler connect to associate fixes #4179 --- src/events/Windows.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 699d72a1..a7e42b35 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -1189,12 +1189,14 @@ void Events::listener_associateX11(void* owner, void* data) { const auto PWINDOW = (CWindow*)owner; PWINDOW->hyprListener_mapWindow.initCallback(&PWINDOW->m_uSurface.xwayland->surface->events.map, &Events::listener_mapWindow, PWINDOW, "XWayland Window"); + PWINDOW->hyprListener_commitWindow.initCallback(&PWINDOW->m_uSurface.xwayland->surface->events.commit, &Events::listener_commitWindow, PWINDOW, "XWayland Window"); } void Events::listener_dissociateX11(void* owner, void* data) { const auto PWINDOW = (CWindow*)owner; PWINDOW->hyprListener_mapWindow.removeCallback(); + PWINDOW->hyprListener_commitWindow.removeCallback(); } void Events::listener_surfaceXWayland(wl_listener* listener, void* data) { @@ -1217,7 +1219,6 @@ void Events::listener_surfaceXWayland(wl_listener* listener, void* data) { PNEWWINDOW->hyprListener_destroyWindow.initCallback(&XWSURFACE->events.destroy, &Events::listener_destroyWindow, PNEWWINDOW, "XWayland Window"); PNEWWINDOW->hyprListener_setOverrideRedirect.initCallback(&XWSURFACE->events.set_override_redirect, &Events::listener_setOverrideRedirect, PNEWWINDOW, "XWayland Window"); PNEWWINDOW->hyprListener_configureX11.initCallback(&XWSURFACE->events.request_configure, &Events::listener_configureX11, PNEWWINDOW, "XWayland Window"); - PNEWWINDOW->hyprListener_commitWindow.initCallback(&XWSURFACE->surface->events.commit, &Events::listener_commitWindow, PNEWWINDOW, "XWayland Window"); } void Events::listener_newXDGToplevel(wl_listener* listener, void* data) { From 460a326c9020f1e9a6bf4157b5a8f1d560b5b536 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 18 Dec 2023 14:45:20 +0000 Subject: [PATCH 400/513] Revert "xdgshell: set predicted tiled windows to monitor res size pre-map" This reverts commit 763d5fa05f7d0191182a1d6cd827415a65293f99. Some issues and fixes #4185 --- src/Window.hpp | 3 +-- src/events/Windows.cpp | 37 +------------------------------------ 2 files changed, 2 insertions(+), 38 deletions(-) diff --git a/src/Window.hpp b/src/Window.hpp index fcd40ba6..cff26052 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -229,8 +229,7 @@ class CWindow { std::string m_szInitialClass = ""; int m_iWorkspaceID = -1; - bool m_bIsMapped = false; - bool m_bInitialCommitPassed = false; + bool m_bIsMapped = false; bool m_bRequestsFloat = false; diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index a7e42b35..46427166 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -791,42 +791,7 @@ void Events::listener_ackConfigure(void* owner, void* data) { void Events::listener_commitWindow(void* owner, void* data) { CWindow* PWINDOW = (CWindow*)owner; - if (!PWINDOW->m_bIsMapped) { - - // dupes shouldn't happen, but you never know, really. - if (PWINDOW->m_bInitialCommitPassed || PWINDOW->m_bIsX11) - return; - - PWINDOW->m_bInitialCommitPassed = true; - - // this is an initial commit of a surface - // in here, the surface will ask us what size we'd like it to be. - // wlroots by default doesn't send anything, so the app can use its preferred floating size - // if we predict it will be tiled, it's better to set it to the monitor size - // so it doesn't appear with the wrong size at the beginning. - // too big > too small, because will be clipped and won't look that bad. - - auto willFloat = g_pXWaylandManager->shouldBeFloated(PWINDOW); - const auto WRULES = g_pConfigManager->getMatchingRules(PWINDOW); - for (auto& r : WRULES) { - if (r.szRule == "float") { - willFloat = true; - break; - } else if (r.szRule == "tile") { - willFloat = false; - break; - } - } - - if (willFloat) - return; - - g_pXWaylandManager->setWindowSize(PWINDOW, g_pCompositor->m_pLastMonitor ? g_pCompositor->m_pLastMonitor->vecSize : Vector2D{1920, 1080}, true); - - return; - } - - if (PWINDOW->isHidden()) + if (!PWINDOW->m_bIsMapped || PWINDOW->isHidden()) return; if (PWINDOW->m_bIsX11) From 0c74df4f9efa0efe6ff1e73c74999acc217f68bb Mon Sep 17 00:00:00 2001 From: dusanx Date: Mon, 18 Dec 2023 16:06:06 +0000 Subject: [PATCH 401/513] renderer: cursor hiding logic improvements (#4184) Co-authored-by: Dusan Popovic --- src/managers/input/InputManager.cpp | 19 ++++++--------- src/render/Renderer.cpp | 37 +++++++++++++++++++---------- src/render/Renderer.hpp | 14 ++++++----- 3 files changed, 39 insertions(+), 31 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index c6904a82..db06de55 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -324,13 +324,11 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { unsetCursorImage(); } - if (g_pHyprRenderer->m_bHasARenderedCursor) { - // TODO: maybe wrap? - if (m_ecbClickBehavior == CLICKMODE_KILL) - setCursorImageOverride("crosshair"); - else - setCursorImageOverride("left_ptr"); - } + // TODO: maybe wrap? + if (m_ecbClickBehavior == CLICKMODE_KILL) + setCursorImageOverride("crosshair"); + else + setCursorImageOverride("left_ptr"); m_bEmptyFocusCursorSet = true; } @@ -490,7 +488,7 @@ void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_even else g_pHyprRenderer->m_bWindowRequestedCursorHide = false; - if (!cursorImageUnlocked() || !g_pHyprRenderer->m_bHasARenderedCursor) + if (!cursorImageUnlocked()) return; if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) { @@ -513,7 +511,7 @@ void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_even } void CInputManager::processMouseRequest(wlr_cursor_shape_manager_v1_request_set_shape_event* e) { - if (!g_pHyprRenderer->m_bHasARenderedCursor || !cursorImageUnlocked()) + if (!cursorImageUnlocked()) return; if (e->seat_client == g_pCompositor->m_sSeat.seat->pointer_state.focused_client) { @@ -555,9 +553,6 @@ void CInputManager::setCursorImageOverride(const std::string& name) { } bool CInputManager::cursorImageUnlocked() { - if (!g_pHyprRenderer->m_bHasARenderedCursor) - return false; - if (m_ecbClickBehavior == CLICKMODE_KILL) return false; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 43d7584c..6136ff9d 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2026,10 +2026,13 @@ void CHyprRenderer::setCursorSurface(wlr_surface* surf, int hotspotX, int hotspo if (surf == m_sLastCursorData.surf) return; - m_sLastCursorData.name = ""; - m_sLastCursorData.surf = surf; + m_sLastCursorData.name = ""; + m_sLastCursorData.surf = surf; + m_sLastCursorData.hotspotX = hotspotX; + m_sLastCursorData.hotspotY = hotspotY; - wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, surf, hotspotX, hotspotY); + if (shouldRenderCursor()) + wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, surf, hotspotX, hotspotY); } void CHyprRenderer::setCursorFromName(const std::string& name) { m_bCursorHasSurface = true; @@ -2040,7 +2043,8 @@ void CHyprRenderer::setCursorFromName(const std::string& name) { m_sLastCursorData.name = name; m_sLastCursorData.surf.reset(); - wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, name.c_str()); + if (shouldRenderCursor()) + wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, name.c_str()); } void CHyprRenderer::ensureCursorRenderingMode() { @@ -2052,20 +2056,27 @@ void CHyprRenderer::ensureCursorRenderingMode() { if (*PCURSORTIMEOUT > 0 || *PHIDEONTOUCH) { const bool HIDE = (*PCURSORTIMEOUT > 0 && *PCURSORTIMEOUT < PASSEDCURSORSECONDS) || (g_pInputManager->m_bLastInputTouch && *PHIDEONTOUCH); - if (HIDE && m_bHasARenderedCursor) { - m_bHasARenderedCursor = false; + if (HIDE && !m_bTimeoutRequestedCursorHide) { + m_bTimeoutRequestedCursorHide = true; - setCursorSurface(nullptr, 0, 0); // hide + wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, nullptr, 0, 0); // hide without saving surface Debug::log(LOG, "Hiding the cursor (timeout)"); for (auto& m : g_pCompositor->m_vMonitors) g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area? - } else if (!HIDE && !m_bHasARenderedCursor) { - m_bHasARenderedCursor = true; + } else if (!HIDE && m_bTimeoutRequestedCursorHide) { + m_bTimeoutRequestedCursorHide = false; - if (!m_bWindowRequestedCursorHide) + if (m_bCursorHasSurface) { // restore last used name or surface, fallback to left_ptr if we don't have one + if (m_sLastCursorData.name == "") { + wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, m_sLastCursorData.surf.value_or(nullptr), m_sLastCursorData.hotspotX, m_sLastCursorData.hotspotY); + } else { + wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, m_sLastCursorData.name.c_str()); + } + } else { setCursorFromName("left_ptr"); + } Debug::log(LOG, "Showing the cursor (timeout)"); @@ -2073,12 +2084,12 @@ void CHyprRenderer::ensureCursorRenderingMode() { g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area? } } else { - m_bHasARenderedCursor = true; + m_bTimeoutRequestedCursorHide = false; } } bool CHyprRenderer::shouldRenderCursor() { - return m_bHasARenderedCursor && m_bCursorHasSurface; + return !m_bTimeoutRequestedCursorHide && !m_bWindowRequestedCursorHide && m_bCursorHasSurface; } std::tuple CHyprRenderer::getRenderTimes(CMonitor* pMonitor) { @@ -2353,4 +2364,4 @@ CRenderbuffer* CHyprRenderer::getCurrentRBO() { bool CHyprRenderer::isNvidia() { return m_bNvidia; -} \ No newline at end of file +} diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index a832802e..5e7b05d6 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -99,6 +99,8 @@ class CHyprRenderer { CTimer m_tRenderTimer; struct { + int hotspotX; + int hotspotY; std::optional surf = nullptr; std::string name; } m_sLastCursorData; @@ -115,12 +117,12 @@ class CHyprRenderer { void renderWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const CBox& geometry); void renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); - bool m_bHasARenderedCursor = true; - bool m_bCursorHasSurface = false; - CRenderbuffer* m_pCurrentRenderbuffer = nullptr; - wlr_buffer* m_pCurrentWlrBuffer = nullptr; - eRenderMode m_eRenderMode = RENDER_MODE_NORMAL; - int m_iLastBufferAge = 0; + bool m_bTimeoutRequestedCursorHide = false; + bool m_bCursorHasSurface = false; + CRenderbuffer* m_pCurrentRenderbuffer = nullptr; + wlr_buffer* m_pCurrentWlrBuffer = nullptr; + eRenderMode m_eRenderMode = RENDER_MODE_NORMAL; + int m_iLastBufferAge = 0; bool m_bNvidia = false; From 11fd37418c8520d9e9ac49856502d1f7d67fae08 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 18 Dec 2023 22:06:50 +0000 Subject: [PATCH 402/513] renderer: fix null cursor surface sets being ignored oopsie from #4184 --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 6136ff9d..985ca977 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2031,7 +2031,7 @@ void CHyprRenderer::setCursorSurface(wlr_surface* surf, int hotspotX, int hotspo m_sLastCursorData.hotspotX = hotspotX; m_sLastCursorData.hotspotY = hotspotY; - if (shouldRenderCursor()) + if (shouldRenderCursor() || !surf) wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, surf, hotspotX, hotspotY); } void CHyprRenderer::setCursorFromName(const std::string& name) { From ef445093f9fbd9a41a91914ef45e6499b3afa54d Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 18 Dec 2023 23:33:10 +0000 Subject: [PATCH 403/513] internal: convert uname fields to strings before logging fixes #4188, thanks @jbeich --- src/debug/CrashReporter.cpp | 4 ++-- src/helpers/MiscFunctions.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/debug/CrashReporter.cpp b/src/debug/CrashReporter.cpp index dac96fb3..ff2a5191 100644 --- a/src/debug/CrashReporter.cpp +++ b/src/debug/CrashReporter.cpp @@ -63,8 +63,8 @@ void CrashReporter::createAndSaveCrash(int sig) { struct utsname unameInfo; uname(&unameInfo); - finalCrashReport += - std::format("\tSystem name: {}\n\tNode name: {}\n\tRelease: {}\n\tVersion: {}\n\n", unameInfo.sysname, unameInfo.nodename, unameInfo.release, unameInfo.version); + finalCrashReport += std::format("\tSystem name: {}\n\tNode name: {}\n\tRelease: {}\n\tVersion: {}\n\n", std::string{unameInfo.sysname}, std::string{unameInfo.nodename}, + std::string{unameInfo.release}, std::string{unameInfo.version}); #if defined(__DragonFly__) || defined(__FreeBSD__) const std::string GPUINFO = execAndGet("pciconf -lv | fgrep -A4 vga"); diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 16650e1b..6eab7e2b 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -577,10 +577,10 @@ void logSystemInfo() { uname(&unameInfo); - Debug::log(LOG, "System name: {}", unameInfo.sysname); - Debug::log(LOG, "Node name: {}", unameInfo.nodename); - Debug::log(LOG, "Release: {}", unameInfo.release); - Debug::log(LOG, "Version: {}", unameInfo.version); + Debug::log(LOG, "System name: {}", std::string{unameInfo.sysname}); + Debug::log(LOG, "Node name: {}", std::string{unameInfo.nodename}); + Debug::log(LOG, "Release: {}", std::string{unameInfo.release}); + Debug::log(LOG, "Version: {}", std::string{unameInfo.version}); Debug::log(NONE, "\n"); From d9b74ff96b3e3f0341a386451b9a3375b6f05503 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 19 Dec 2023 11:55:56 +0000 Subject: [PATCH 404/513] renderer: staticize local functions --- src/render/Renderer.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 985ca977..d0fb7212 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -51,7 +51,7 @@ CHyprRenderer::CHyprRenderer() { Debug::log(WARN, "NVIDIA detected, please remember to follow nvidia instructions on the wiki"); } -void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { +static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { const auto TEXTURE = wlr_surface_get_texture(surface); const auto RDATA = (SRenderData*)data; @@ -1348,7 +1348,7 @@ void CHyprRenderer::outputMgrApplyTest(wlr_output_configuration_v1* config, bool // taken from Sway. // this is just too much of a spaghetti for me to understand -void apply_exclusive(struct wlr_box* usable_area, uint32_t anchor, int32_t exclusive, int32_t margin_top, int32_t margin_right, int32_t margin_bottom, int32_t margin_left) { +static void applyExclusive(wlr_box& usableArea, uint32_t anchor, int32_t exclusive, int32_t marginTop, int32_t marginRight, int32_t marginBottom, int32_t marginLeft) { if (exclusive <= 0) { return; } @@ -1363,33 +1363,33 @@ void apply_exclusive(struct wlr_box* usable_area, uint32_t anchor, int32_t exclu { .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP, .anchor_triplet = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP, - .positive_axis = &usable_area->y, - .negative_axis = &usable_area->height, - .margin = margin_top, + .positive_axis = &usableArea.y, + .negative_axis = &usableArea.height, + .margin = marginTop, }, // Bottom { .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, .anchor_triplet = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, .positive_axis = NULL, - .negative_axis = &usable_area->height, - .margin = margin_bottom, + .negative_axis = &usableArea.height, + .margin = marginBottom, }, // Left { .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT, .anchor_triplet = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, - .positive_axis = &usable_area->x, - .negative_axis = &usable_area->width, - .margin = margin_left, + .positive_axis = &usableArea.x, + .negative_axis = &usableArea.width, + .margin = marginLeft, }, // Right { .singular_anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT, .anchor_triplet = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM, .positive_axis = NULL, - .negative_axis = &usable_area->width, - .margin = margin_right, + .negative_axis = &usableArea.width, + .margin = marginRight, }, }; for (size_t i = 0; i < sizeof(edges) / sizeof(edges[0]); ++i) { @@ -1480,7 +1480,7 @@ void CHyprRenderer::arrangeLayerArray(CMonitor* pMonitor, const std::vectorgeometry = box; - apply_exclusive(usableArea->pWlr(), PSTATE->anchor, PSTATE->exclusive_zone, PSTATE->margin.top, PSTATE->margin.right, PSTATE->margin.bottom, PSTATE->margin.left); + applyExclusive(*usableArea->pWlr(), PSTATE->anchor, PSTATE->exclusive_zone, PSTATE->margin.top, PSTATE->margin.right, PSTATE->margin.bottom, PSTATE->margin.left); usableArea->applyFromWlr(); From 3771c49a94806b317fe4de470e96ae589b660a1b Mon Sep 17 00:00:00 2001 From: Husam Harazi Date: Wed, 20 Dec 2023 14:56:15 +0300 Subject: [PATCH 405/513] filesystem: Set the sticky bit on `/tmp/hypr` (#4199) To prevent unprivileged users from deleting other users' files. --- src/Compositor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index cbdfa288..ab478a87 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -50,7 +50,7 @@ CCompositor::CCompositor() { if (!std::filesystem::exists("/tmp/hypr")) { std::filesystem::create_directory("/tmp/hypr"); - std::filesystem::permissions("/tmp/hypr", std::filesystem::perms::all, std::filesystem::perm_options::replace); + std::filesystem::permissions("/tmp/hypr", std::filesystem::perms::all | std::filesystem::perms::sticky_bit, std::filesystem::perm_options::replace); } const auto INSTANCEPATH = "/tmp/hypr/" + m_szInstanceSignature; From d1b8a63a8ef1d7258d49854d2256fa9b99fd99bc Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 20 Dec 2023 13:00:27 +0100 Subject: [PATCH 406/513] input: allow setting cursor even if it's hidden ref #4197 --- src/render/Renderer.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index d0fb7212..a5cc8055 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2031,9 +2031,9 @@ void CHyprRenderer::setCursorSurface(wlr_surface* surf, int hotspotX, int hotspo m_sLastCursorData.hotspotX = hotspotX; m_sLastCursorData.hotspotY = hotspotY; - if (shouldRenderCursor() || !surf) - wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, surf, hotspotX, hotspotY); + wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, surf, hotspotX, hotspotY); } + void CHyprRenderer::setCursorFromName(const std::string& name) { m_bCursorHasSurface = true; @@ -2043,8 +2043,7 @@ void CHyprRenderer::setCursorFromName(const std::string& name) { m_sLastCursorData.name = name; m_sLastCursorData.surf.reset(); - if (shouldRenderCursor()) - wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, name.c_str()); + wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, name.c_str()); } void CHyprRenderer::ensureCursorRenderingMode() { From b4f4bd38e8a0d9afd30231cf999e73548bef5760 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 20 Dec 2023 13:07:12 +0100 Subject: [PATCH 407/513] configmanager: set a limit to config variable substitutions fixes #4198 --- src/config/ConfigManager.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 8afa627d..8ecfa87b 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1478,7 +1478,10 @@ std::string CConfigManager::parseKeyword(const std::string& COMMAND, const std:: void CConfigManager::applyUserDefinedVars(std::string& line, const size_t equalsPlace) { auto dollarPlace = line.find_first_of('$', equalsPlace); + int times = 0; + while (dollarPlace != std::string::npos) { + times++; const auto STRAFTERDOLLAR = line.substr(dollarPlace + 1); bool found = false; @@ -1501,6 +1504,13 @@ void CConfigManager::applyUserDefinedVars(std::string& line, const size_t equals } dollarPlace = line.find_first_of('$', dollarPlace + 1); + + if (times > 256 /* arbitrary limit */) { + line = ""; + parseError = "Maximum variable recursion limit hit. Evaluating the line led to too many variable substitutions."; + Debug::log(ERR, "Variable recursion limit hit in configmanager"); + break; + } } } From 53c78ab90676ebd8034950a7573137921f875177 Mon Sep 17 00:00:00 2001 From: Junxuan Liao <70618504+MikeWalrus@users.noreply.github.com> Date: Thu, 21 Dec 2023 00:53:54 +0800 Subject: [PATCH 408/513] idle: notify idle on tablet inputs (#4201) Fixes #4028. --- src/managers/input/Tablets.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/managers/input/Tablets.cpp b/src/managers/input/Tablets.cpp index 2c1681c1..959ce432 100644 --- a/src/managers/input/Tablets.cpp +++ b/src/managers/input/Tablets.cpp @@ -90,6 +90,8 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) { if (EVENT->updated_axes & (WLR_TABLET_TOOL_AXIS_TILT_X | WLR_TABLET_TOOL_AXIS_TILT_Y)) wlr_tablet_v2_tablet_tool_notify_tilt(PTOOL->wlrTabletToolV2, PTOOL->tiltX, PTOOL->tiltY); + + g_pCompositor->notifyIdleActivity(); }, PNEWTABLET, "Tablet"); @@ -109,6 +111,8 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) { } else { wlr_send_tablet_v2_tablet_tool_up(PTOOL->wlrTabletToolV2); } + + g_pCompositor->notifyIdleActivity(); }, PNEWTABLET, "Tablet"); @@ -120,6 +124,7 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) { const auto PTOOL = g_pInputManager->ensureTabletToolPresent(EVENT->tool); wlr_tablet_v2_tablet_tool_notify_button(PTOOL->wlrTabletToolV2, (zwp_tablet_pad_v2_button_state)EVENT->button, (zwp_tablet_pad_v2_button_state)EVENT->state); + g_pCompositor->notifyIdleActivity(); }, PNEWTABLET, "Tablet"); @@ -144,6 +149,8 @@ void CInputManager::newTabletTool(wlr_input_device* pDevice) { g_pInputManager->refocus(); g_pInputManager->focusTablet(PTAB, EVENT->tool); } + + g_pCompositor->notifyIdleActivity(); }, PNEWTABLET, "Tablet"); From a197fe3c11d5ac095bf8e2f491edf28bde9f9b49 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 20 Dec 2023 17:59:11 +0100 Subject: [PATCH 409/513] renderer: don't set surfaces on cursor timeout --- src/render/Renderer.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index a5cc8055..6e054a47 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2058,8 +2058,6 @@ void CHyprRenderer::ensureCursorRenderingMode() { if (HIDE && !m_bTimeoutRequestedCursorHide) { m_bTimeoutRequestedCursorHide = true; - wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, nullptr, 0, 0); // hide without saving surface - Debug::log(LOG, "Hiding the cursor (timeout)"); for (auto& m : g_pCompositor->m_vMonitors) @@ -2067,16 +2065,6 @@ void CHyprRenderer::ensureCursorRenderingMode() { } else if (!HIDE && m_bTimeoutRequestedCursorHide) { m_bTimeoutRequestedCursorHide = false; - if (m_bCursorHasSurface) { // restore last used name or surface, fallback to left_ptr if we don't have one - if (m_sLastCursorData.name == "") { - wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, m_sLastCursorData.surf.value_or(nullptr), m_sLastCursorData.hotspotX, m_sLastCursorData.hotspotY); - } else { - wlr_cursor_set_xcursor(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sWLRXCursorMgr, m_sLastCursorData.name.c_str()); - } - } else { - setCursorFromName("left_ptr"); - } - Debug::log(LOG, "Showing the cursor (timeout)"); for (auto& m : g_pCompositor->m_vMonitors) From 48ecb13b14d99241725a65582edf42cd51843e94 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 20 Dec 2023 21:40:44 +0100 Subject: [PATCH 410/513] renderer: improve cursor hiding infra ref #4197 --- src/render/Renderer.cpp | 43 ++++++++++++++++++++++++++++++----------- src/render/Renderer.hpp | 17 ++++++++-------- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 6e054a47..49bc84bd 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2020,10 +2020,10 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR return true; } -void CHyprRenderer::setCursorSurface(wlr_surface* surf, int hotspotX, int hotspotY) { +void CHyprRenderer::setCursorSurface(wlr_surface* surf, int hotspotX, int hotspotY, bool force) { m_bCursorHasSurface = surf; - if (surf == m_sLastCursorData.surf) + if ((surf == m_sLastCursorData.surf || m_bCursorHidden) && !force) return; m_sLastCursorData.name = ""; @@ -2034,10 +2034,10 @@ void CHyprRenderer::setCursorSurface(wlr_surface* surf, int hotspotX, int hotspo wlr_cursor_set_surface(g_pCompositor->m_sWLRCursor, surf, hotspotX, hotspotY); } -void CHyprRenderer::setCursorFromName(const std::string& name) { +void CHyprRenderer::setCursorFromName(const std::string& name, bool force) { m_bCursorHasSurface = true; - if (name == m_sLastCursorData.name) + if ((name == m_sLastCursorData.name || m_bCursorHidden) && !force) return; m_sLastCursorData.name = name; @@ -2055,28 +2055,49 @@ void CHyprRenderer::ensureCursorRenderingMode() { if (*PCURSORTIMEOUT > 0 || *PHIDEONTOUCH) { const bool HIDE = (*PCURSORTIMEOUT > 0 && *PCURSORTIMEOUT < PASSEDCURSORSECONDS) || (g_pInputManager->m_bLastInputTouch && *PHIDEONTOUCH); - if (HIDE && !m_bTimeoutRequestedCursorHide) { - m_bTimeoutRequestedCursorHide = true; - + if (HIDE && !m_bCursorHidden) { Debug::log(LOG, "Hiding the cursor (timeout)"); for (auto& m : g_pCompositor->m_vMonitors) g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area? - } else if (!HIDE && m_bTimeoutRequestedCursorHide) { - m_bTimeoutRequestedCursorHide = false; + setCursorHidden(true); + + } else if (!HIDE && m_bCursorHidden) { Debug::log(LOG, "Showing the cursor (timeout)"); for (auto& m : g_pCompositor->m_vMonitors) g_pHyprRenderer->damageMonitor(m.get()); // TODO: maybe just damage the cursor area? + + setCursorHidden(false); } } else { - m_bTimeoutRequestedCursorHide = false; + setCursorHidden(false); } } +void CHyprRenderer::setCursorHidden(bool hide) { + + if (hide == m_bCursorHidden) + return; + + m_bCursorHidden = hide; + + if (hide) { + wlr_cursor_unset_image(g_pCompositor->m_sWLRCursor); + return; + } + + if (m_sLastCursorData.surf.has_value()) + setCursorSurface(m_sLastCursorData.surf.value(), m_sLastCursorData.hotspotX, m_sLastCursorData.hotspotY, true); + else if (!m_sLastCursorData.name.empty()) + setCursorFromName(m_sLastCursorData.name, true); + else + setCursorFromName("left_ptr", true); +} + bool CHyprRenderer::shouldRenderCursor() { - return !m_bTimeoutRequestedCursorHide && !m_bWindowRequestedCursorHide && m_bCursorHasSurface; + return !m_bCursorHidden && !m_bWindowRequestedCursorHide && m_bCursorHasSurface; } std::tuple CHyprRenderer::getRenderTimes(CMonitor* pMonitor) { diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 5e7b05d6..32815344 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -56,14 +56,15 @@ class CHyprRenderer { bool shouldRenderWindow(CWindow*); void ensureCursorRenderingMode(); bool shouldRenderCursor(); + void setCursorHidden(bool hide); void calculateUVForSurface(CWindow*, wlr_surface*, bool main = false); std::tuple getRenderTimes(CMonitor* pMonitor); // avg max min void renderLockscreen(CMonitor* pMonitor, timespec* now); void setOccludedForBackLayers(CRegion& region, CWorkspace* pWorkspace); bool canSkipBackBufferClear(CMonitor* pMonitor); void recheckSolitaryForMonitor(CMonitor* pMonitor); - void setCursorSurface(wlr_surface* surf, int hotspotX, int hotspotY); - void setCursorFromName(const std::string& name); + void setCursorSurface(wlr_surface* surf, int hotspotX, int hotspotY, bool force = false); + void setCursorFromName(const std::string& name, bool force = false); void renderSoftwareCursors(CMonitor* pMonitor, const CRegion& damage, std::optional overridePos = {}); void onRenderbufferDestroy(CRenderbuffer* rb); CRenderbuffer* getCurrentRBO(); @@ -117,12 +118,12 @@ class CHyprRenderer { void renderWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const CBox& geometry); void renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); - bool m_bTimeoutRequestedCursorHide = false; - bool m_bCursorHasSurface = false; - CRenderbuffer* m_pCurrentRenderbuffer = nullptr; - wlr_buffer* m_pCurrentWlrBuffer = nullptr; - eRenderMode m_eRenderMode = RENDER_MODE_NORMAL; - int m_iLastBufferAge = 0; + bool m_bCursorHidden = false; + bool m_bCursorHasSurface = false; + CRenderbuffer* m_pCurrentRenderbuffer = nullptr; + wlr_buffer* m_pCurrentWlrBuffer = nullptr; + eRenderMode m_eRenderMode = RENDER_MODE_NORMAL; + int m_iLastBufferAge = 0; bool m_bNvidia = false; From 4eb42fab7bb1b1d6c8fec4682c8c1de6dca7049b Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 20 Dec 2023 23:52:18 +0100 Subject: [PATCH 411/513] windowrules: add onworkspace cool --- src/Compositor.cpp | 12 +++++++++++ src/Compositor.hpp | 1 + src/Window.cpp | 4 ++++ src/Window.hpp | 13 +++++------ src/config/ConfigManager.cpp | 42 ++++++++++++++++++++++++++++-------- 5 files changed, 57 insertions(+), 15 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index ab478a87..5241fde8 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1814,6 +1814,15 @@ void CCompositor::updateAllWindowsAnimatedDecorationValues() { } } +void CCompositor::updateWorkspaceWindows(const int64_t& id) { + for (auto& w : m_vWindows) { + if (!w->m_bIsMapped || w->m_iWorkspaceID != id) + continue; + + w->updateDynamicRules(); + } +} + void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) { // optimization static auto* const ACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.active_border")->data.get(); @@ -2643,6 +2652,9 @@ void CCompositor::moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorks if (FULLSCREEN) setWindowFullscreen(pWindow, true, FULLSCREENMODE); + + g_pCompositor->updateWorkspaceWindows(pWorkspace->m_iID); + g_pCompositor->updateWorkspaceWindows(pWindow->m_iWorkspaceID); } CWindow* CCompositor::getForceFocus() { diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 65550154..8703f3f1 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -172,6 +172,7 @@ class CCompositor { CWindow* getConstraintWindow(SMouse*); CMonitor* getMonitorInDirection(const char&); void updateAllWindowsAnimatedDecorationValues(); + void updateWorkspaceWindows(const int64_t& id); void updateWindowAnimatedDecorationValues(CWindow*); int getNextAvailableMonitorID(std::string const& name); void moveWorkspaceToMonitor(CWorkspace*, CMonitor*); diff --git a/src/Window.cpp b/src/Window.cpp index da0912ee..11627d5c 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -448,6 +448,8 @@ void CWindow::onUnmap() { if (PMONITOR && PMONITOR->solitaryClient == this) PMONITOR->solitaryClient = nullptr; + + g_pCompositor->updateWorkspaceWindows(m_iWorkspaceID); } void CWindow::onMap() { @@ -485,6 +487,8 @@ void CWindow::onMap() { "CWindow"); m_vReportedSize = m_vPendingReportedSize; + + g_pCompositor->updateWorkspaceWindows(m_iWorkspaceID); } void CWindow::onBorderAngleAnimEnd(void* ptr) { diff --git a/src/Window.hpp b/src/Window.hpp index cff26052..8d5f22e5 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -151,12 +151,13 @@ struct SWindowRule { bool v2 = false; std::string szTitle; std::string szClass; - int bX11 = -1; // -1 means "ANY" - int bFloating = -1; - int bFullscreen = -1; - int bPinned = -1; - int bFocus = -1; - std::string szWorkspace = ""; // empty means any + int bX11 = -1; // -1 means "ANY" + int bFloating = -1; + int bFullscreen = -1; + int bPinned = -1; + int bFocus = -1; + int iOnWorkspace = -1; + std::string szWorkspace = ""; // empty means any }; class CWindow { diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 8ecfa87b..fb5c7b02 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1026,17 +1026,28 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s rule.szRule = RULE; rule.szValue = VALUE; - const auto TITLEPOS = VALUE.find("title:"); - const auto CLASSPOS = VALUE.find("class:"); - const auto X11POS = VALUE.find("xwayland:"); - const auto FLOATPOS = VALUE.find("floating:"); - const auto FULLSCREENPOS = VALUE.find("fullscreen:"); - const auto PINNEDPOS = VALUE.find("pinned:"); - const auto WORKSPACEPOS = VALUE.find("workspace:"); - const auto FOCUSPOS = VALUE.find("focus:"); + const auto TITLEPOS = VALUE.find("title:"); + const auto CLASSPOS = VALUE.find("class:"); + const auto X11POS = VALUE.find("xwayland:"); + const auto FLOATPOS = VALUE.find("floating:"); + const auto FULLSCREENPOS = VALUE.find("fullscreen:"); + const auto PINNEDPOS = VALUE.find("pinned:"); + const auto FOCUSPOS = VALUE.find("focus:"); + const auto ONWORKSPACEPOS = VALUE.find("onworkspace:"); + + // find workspacepos that isn't onworkspacepos + size_t WORKSPACEPOS = std::string::npos; + size_t currentPos = 0; + while (currentPos != std::string::npos) { + if (currentPos > 0 && VALUE[currentPos - 1] != 'n') { + WORKSPACEPOS = currentPos; + break; + } + currentPos = VALUE.find("workspace:", currentPos + 1); + } if (TITLEPOS == std::string::npos && CLASSPOS == std::string::npos && X11POS == std::string::npos && FLOATPOS == std::string::npos && FULLSCREENPOS == std::string::npos && - PINNEDPOS == std::string::npos && WORKSPACEPOS == std::string::npos && FOCUSPOS == std::string::npos) { + PINNEDPOS == std::string::npos && WORKSPACEPOS == std::string::npos && FOCUSPOS == std::string::npos && ONWORKSPACEPOS == std::string::npos) { Debug::log(ERR, "Invalid rulev2 syntax: {}", VALUE); parseError = "Invalid rulev2 syntax: " + VALUE; return; @@ -1059,6 +1070,8 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s min = FULLSCREENPOS; if (PINNEDPOS > pos && PINNEDPOS < min) min = PINNEDPOS; + if (ONWORKSPACEPOS > pos && ONWORKSPACEPOS < min) + min = ONWORKSPACEPOS; if (WORKSPACEPOS > pos && WORKSPACEPOS < min) min = WORKSPACEPOS; if (FOCUSPOS > pos && FOCUSPOS < min) @@ -1098,6 +1111,9 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s if (FOCUSPOS != std::string::npos) rule.bFocus = extract(FOCUSPOS + 6) == "1" ? 1 : 0; + if (ONWORKSPACEPOS != std::string::npos) + rule.iOnWorkspace = configStringToInt(extract(ONWORKSPACEPOS + 12)); + if (RULE == "unset") { std::erase_if(m_dWindowRules, [&](const SWindowRule& other) { if (!other.v2) { @@ -1127,6 +1143,9 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s if (rule.bFocus != -1 && rule.bFocus != other.bFocus) return false; + if (rule.iOnWorkspace != -1 && rule.iOnWorkspace != other.iOnWorkspace) + return false; + return true; } }); @@ -2012,6 +2031,11 @@ std::vector CConfigManager::getMatchingRules(CWindow* pWindow) { continue; } + if (rule.iOnWorkspace != -1) { + if (rule.iOnWorkspace != g_pCompositor->getWindowsOnWorkspace(pWindow->m_iWorkspaceID)) + continue; + } + if (!rule.szWorkspace.empty()) { const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID); From 79f3888b4bd9796850189ed3e151a6c831e6faae Mon Sep 17 00:00:00 2001 From: Ahmed Yasser Date: Thu, 21 Dec 2023 00:54:52 +0200 Subject: [PATCH 412/513] signal: fix invalid pointer access (#4207) --- src/Compositor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 5241fde8..c7be0662 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -24,7 +24,7 @@ void handleUnrecoverableSignal(int sig) { signal(SIGABRT, SIG_DFL); signal(SIGSEGV, SIG_DFL); - if (g_pHookSystem->m_bCurrentEventPlugin) { + if (g_pHookSystem && g_pHookSystem->m_bCurrentEventPlugin) { longjmp(g_pHookSystem->m_jbHookFaultJumpBuf, 1); return; } From 698f3b65765fc4b0cae0592f65663c70e593898d Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 21 Dec 2023 22:01:50 +0100 Subject: [PATCH 413/513] hyprpm: trim paths in PATH fixes #4210 --- hyprpm/src/core/PluginManager.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index c69533ee..e28637fd 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -13,7 +13,26 @@ #include -std::string execAndGet(std::string cmd) { +static std::string removeBeginEndSpacesTabs(std::string str) { + if (str.empty()) + return str; + + int countBefore = 0; + while (str[countBefore] == ' ' || str[countBefore] == '\t') { + countBefore++; + } + + int countAfter = 0; + while ((int)str.length() - countAfter - 1 >= 0 && (str[str.length() - countAfter - 1] == ' ' || str[str.length() - 1 - countAfter] == '\t')) { + countAfter++; + } + + str = str.substr(countBefore, str.length() - countBefore - countAfter); + + return str; +} + +static std::string execAndGet(std::string cmd) { cmd += " 2>&1"; std::array buffer; std::string result; @@ -265,7 +284,7 @@ eHeadersErrors CPluginManager::headersValid() { if (PATH.ends_with("protocols") || PATH.ends_with("wlroots")) continue; - verHeader = PATH.substr(2) + "/hyprland/src/version.h"; + verHeader = removeBeginEndSpacesTabs(PATH.substr(2)) + "/hyprland/src/version.h"; break; } From bc51a91043a6405834854d8a13e8e8ac45ea5737 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 21 Dec 2023 22:18:07 +0100 Subject: [PATCH 414/513] crashreporter: don't explicitly set 777 on crash report directory fixes #4218 --- src/debug/CrashReporter.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/debug/CrashReporter.cpp b/src/debug/CrashReporter.cpp index ff2a5191..65b31399 100644 --- a/src/debug/CrashReporter.cpp +++ b/src/debug/CrashReporter.cpp @@ -130,19 +130,15 @@ void CrashReporter::createAndSaveCrash(int sig) { std::ofstream ofs; std::string path; if (!CACHE_HOME || std::string(CACHE_HOME).empty()) { - if (!std::filesystem::exists(std::string(HOME) + "/.hyprland")) { + if (!std::filesystem::exists(std::string(HOME) + "/.hyprland")) std::filesystem::create_directory(std::string(HOME) + "/.hyprland"); - std::filesystem::permissions(std::string(HOME) + "/.hyprland", std::filesystem::perms::all, std::filesystem::perm_options::replace); - } path = std::string(HOME) + "/.hyprland/hyprlandCrashReport" + std::to_string(PID) + ".txt"; ofs.open(path, std::ios::trunc); } else { - if (!std::filesystem::exists(std::string(CACHE_HOME) + "/hyprland")) { + if (!std::filesystem::exists(std::string(CACHE_HOME) + "/hyprland")) std::filesystem::create_directory(std::string(CACHE_HOME) + "/hyprland"); - std::filesystem::permissions(std::string(CACHE_HOME) + "/hyprland", std::filesystem::perms::all, std::filesystem::perm_options::replace); - } path = std::string(CACHE_HOME) + "/hyprland/hyprlandCrashReport" + std::to_string(PID) + ".txt"; ofs.open(path, std::ios::trunc); From bd952dcef2ead3b0b7e2d730930a3fc528813ee0 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 21 Dec 2023 22:27:12 +0100 Subject: [PATCH 415/513] systemd: add HYPRLAND_NO_SD_NOTIFY fixes #4217 --- src/Compositor.cpp | 18 ++++++++---------- src/helpers/MiscFunctions.cpp | 7 +++++++ src/helpers/MiscFunctions.hpp | 1 + src/main.cpp | 2 +- src/render/Renderer.cpp | 4 +--- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index c7be0662..e4243a4e 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -125,13 +125,12 @@ void CCompositor::initServer() { initManagers(STAGE_PRIORITY); - if (const auto ENV = getenv("HYPRLAND_TRACE"); ENV && std::string(ENV) == "1") + if (envEnabled("HYPRLAND_TRACE")) Debug::trace = true; wlr_log_init(WLR_INFO, NULL); - const auto LOGWLR = getenv("HYPRLAND_LOG_WLR"); - if (LOGWLR && std::string(LOGWLR) == "1") + if (envEnabled("HYPRLAND_LOG_WLR")) wlr_log_init(WLR_DEBUG, Debug::wlrLog); else wlr_log_init(WLR_ERROR, Debug::wlrLog); @@ -343,7 +342,7 @@ void CCompositor::cleanup() { Debug::shuttingDown = true; #ifdef USES_SYSTEMD - if (sd_booted() > 0) + if (sd_booted() > 0 && !envEnabled("HYPRLAND_NO_SD_NOTIFY")) sd_notify(0, "STOPPING=1"); #endif @@ -540,10 +539,11 @@ void CCompositor::startCompositor() { g_pHyprRenderer->setCursorFromName("left_ptr"); #ifdef USES_SYSTEMD - if (sd_booted() > 0) + if (sd_booted() > 0) { // tell systemd that we are ready so it can start other bond, following, related units - sd_notify(0, "READY=1"); - else + if (!envEnabled("HYPRLAND_NO_SD_NOTIFY")) + sd_notify(0, "READY=1"); + } else Debug::log(LOG, "systemd integration is baked in but system itself is not booted à la systemd!"); #endif @@ -2598,9 +2598,7 @@ int CCompositor::getNewSpecialID() { } void CCompositor::performUserChecks() { - const auto atomicEnv = getenv("WLR_DRM_NO_ATOMIC"); - const auto atomicEnvStr = std::string(atomicEnv ? atomicEnv : ""); - if (g_pConfigManager->getInt("general:allow_tearing") == 1 && atomicEnvStr != "1") { + if (g_pConfigManager->getInt("general:allow_tearing") == 1 && !envEnabled("WLR_DRM_NO_ATOMIC")) { g_pHyprNotificationOverlay->addNotification("You have enabled tearing, but immediate presentations are not available on your configuration. Try adding " "env = WLR_DRM_NO_ATOMIC,1 to your config.", CColor(0), 15000, ICON_WARNING); diff --git a/src/helpers/MiscFunctions.cpp b/src/helpers/MiscFunctions.cpp index 6eab7e2b..5eb99bfd 100644 --- a/src/helpers/MiscFunctions.cpp +++ b/src/helpers/MiscFunctions.cpp @@ -791,4 +791,11 @@ uint32_t glFormatToType(uint32_t gl) { GL_UNSIGNED_INT_2_10_10_10_REV : #endif GL_UNSIGNED_BYTE; +} + +bool envEnabled(const std::string& env) { + const auto ENV = getenv(env.c_str()); + if (!ENV) + return false; + return std::string(ENV) == "1"; } \ No newline at end of file diff --git a/src/helpers/MiscFunctions.hpp b/src/helpers/MiscFunctions.hpp index d8070c76..1ccbdc0e 100644 --- a/src/helpers/MiscFunctions.hpp +++ b/src/helpers/MiscFunctions.hpp @@ -35,6 +35,7 @@ std::vector getBacktrace(); void throwError(const std::string& err); uint32_t drmFormatToGL(uint32_t drm); uint32_t glFormatToType(uint32_t gl); +bool envEnabled(const std::string& env); template [[deprecated("use std::format instead")]] std::string getFormat(std::format_string fmt, Args&&... args) { diff --git a/src/main.cpp b/src/main.cpp index 86c44857..2edf3601 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -102,7 +102,7 @@ int main(int argc, char** argv) { g_pCompositor->initServer(); - if (!getenv("HYPRLAND_NO_RT") || configStringToInt(std::string(getenv("HYPRLAND_NO_RT"))) == 0) + if (!envEnabled("HYPRLAND_NO_RT")) Init::gainRealTime(); Debug::log(LOG, "Hyprland init finished."); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 49bc84bd..2397849a 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -9,9 +9,7 @@ extern "C" { } CHyprRenderer::CHyprRenderer() { - const auto ENV = getenv("WLR_DRM_NO_ATOMIC"); - - if (ENV && std::string(ENV) == "1") + if (envEnabled("WLR_DRM_NO_ATOMIC")) m_bTearingEnvSatisfied = true; if (g_pCompositor->m_sWLRSession) { From 7cec618fe47e457fe66ef772da00ef07665a8607 Mon Sep 17 00:00:00 2001 From: thejch <66577496+thejch@users.noreply.github.com> Date: Fri, 22 Dec 2023 03:37:38 -0800 Subject: [PATCH 416/513] master: add dispatchers rollnext and rollprev (#4209) --- src/layout/MasterLayout.cpp | 44 +++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 086bcdac..def03236 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -1332,6 +1332,50 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri nd.percMaster = std::clamp(newMfact, 0.05f, 0.95f); } } + } else if (command == "rollnext") { + const auto PWINDOW = header.pWindow; + const auto PNODE = getNodeFromWindow(PWINDOW); + + const auto OLDMASTER = PNODE->isMaster ? PNODE : getMasterNodeOnWorkspace(PNODE->workspaceID); + const auto OLDMASTERIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *OLDMASTER); + + for (auto& nd : m_lMasterNodesData) { + if (nd.workspaceID == PNODE->workspaceID && !nd.isMaster) { + nd.isMaster = true; + const auto NEWMASTERIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), nd); + m_lMasterNodesData.splice(OLDMASTERIT, m_lMasterNodesData, NEWMASTERIT); + const bool inheritFullscreen = prepareLoseFocus(PWINDOW); + switchToWindow(nd.pWindow); + prepareNewFocus(nd.pWindow, inheritFullscreen); + OLDMASTER->isMaster = false; + m_lMasterNodesData.splice(m_lMasterNodesData.end(), m_lMasterNodesData, OLDMASTERIT); + break; + } + } + + recalculateMonitor(PWINDOW->m_iMonitorID); + } else if (command == "rollprev") { + const auto PWINDOW = header.pWindow; + const auto PNODE = getNodeFromWindow(PWINDOW); + + const auto OLDMASTER = PNODE->isMaster ? PNODE : getMasterNodeOnWorkspace(PNODE->workspaceID); + const auto OLDMASTERIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *OLDMASTER); + + for (auto& nd : m_lMasterNodesData | std::views::reverse) { + if (nd.workspaceID == PNODE->workspaceID && !nd.isMaster) { + nd.isMaster = true; + const auto NEWMASTERIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), nd); + m_lMasterNodesData.splice(OLDMASTERIT, m_lMasterNodesData, NEWMASTERIT); + const bool inheritFullscreen = prepareLoseFocus(PWINDOW); + switchToWindow(nd.pWindow); + prepareNewFocus(nd.pWindow, inheritFullscreen); + OLDMASTER->isMaster = false; + m_lMasterNodesData.splice(m_lMasterNodesData.begin(), m_lMasterNodesData, OLDMASTERIT); + break; + } + } + + recalculateMonitor(PWINDOW->m_iMonitorID); } return 0; From 37d2840246af43a7141e2a036820fc3dec468f01 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 22 Dec 2023 19:54:05 +0100 Subject: [PATCH 417/513] renderer: reject non-clean scales, find nearest clean --- src/helpers/Monitor.hpp | 3 ++- src/render/Renderer.cpp | 40 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index f44e2c16..2b196c96 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -40,7 +40,8 @@ class CMonitor { uint64_t ID = -1; int activeWorkspace = -1; - float scale = 1; + float setScale = 1; // scale set by cfg + float scale = 1; // real scale std::string szName = ""; std::string szDescription = ""; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 2397849a..b56c275e 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1704,7 +1704,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR // Check if the rule isn't already applied // TODO: clean this up lol if (!force && DELTALESSTHAN(pMonitor->vecPixelSize.x, pMonitorRule->resolution.x, 1) && DELTALESSTHAN(pMonitor->vecPixelSize.y, pMonitorRule->resolution.y, 1) && - DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->scale == pMonitorRule->scale && + DELTALESSTHAN(pMonitor->refreshRate, pMonitorRule->refreshRate, 1) && pMonitor->setScale == pMonitorRule->scale && ((DELTALESSTHAN(pMonitor->vecPosition.x, pMonitorRule->offset.x, 1) && DELTALESSTHAN(pMonitor->vecPosition.y, pMonitorRule->offset.y, 1)) || pMonitorRule->offset == Vector2D(-INT32_MAX, -INT32_MAX)) && pMonitor->transform == pMonitorRule->transform && pMonitorRule->enable10bit == pMonitor->enabled10bit && @@ -1726,6 +1726,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->scale = DEFAULTSCALE; } + pMonitor->setScale = pMonitor->scale; + wlr_output_set_transform(pMonitor->output, pMonitorRule->transform); pMonitor->transform = pMonitorRule->transform; @@ -1942,6 +1944,42 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->vecPixelSize = pMonitor->vecSize; + Vector2D logicalSize = pMonitor->vecPixelSize / pMonitor->scale; + if (logicalSize.x != std::round(logicalSize.x) || logicalSize.y != std::round(logicalSize.y)) { + // invalid scale, will produce fractional pixels. + // find the nearest valid. + + float searchScale = std::round(pMonitor->scale * 360.0); + bool found = false; + + for (size_t i = 0; i < 90; ++i) { + double scaleUp = (searchScale + i) / 360.0; + double scaleDown = (searchScale - i) / 360.0; + + Vector2D logicalUp = pMonitor->vecPixelSize / scaleUp; + Vector2D logicalDown = pMonitor->vecPixelSize / scaleDown; + + if (logicalUp == logicalUp.round()) { + found = true; + searchScale = scaleUp; + break; + } + if (logicalDown == logicalDown.round()) { + found = true; + searchScale = scaleDown; + break; + } + } + + if (!found) { + Debug::log(ERR, "Invalid scale passed to monitor, {} failed to find a clean divisor", pMonitor->scale); + g_pConfigManager->addParseError("Invalid scale passed to monitor " + pMonitor->szName + ", failed to find a clean divisor"); + } else { + Debug::log(WARN, "Invalid scale ({}) passed to monitor, adjusting to {}", pMonitor->scale, searchScale); + pMonitor->scale = searchScale; + } + } + // clang-format off static const std::array>, 2> formats{ std::vector>{ /* 10-bit */ From c416880cf96aee783b6a00f356512e5d758e6056 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 22 Dec 2023 19:54:18 +0100 Subject: [PATCH 418/513] shadow: correctly scale boxes --- src/render/decorations/CHyprDropShadowDecoration.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 5e70b639..0f848c61 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -119,10 +119,12 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D windowBox.translate(-pMonitor->vecPosition + WORKSPACEOFFSET); withDecos.translate(-pMonitor->vecPosition + WORKSPACEOFFSET); - auto extentss = withDecos.extentsFrom(windowBox); + auto scaledExtentss = withDecos.extentsFrom(windowBox); + scaledExtentss = scaledExtentss * pMonitor->scale; + scaledExtentss = scaledExtentss.round(); // add extents - windowBox.addExtents(extentss).scale(pMonitor->scale).round(); + windowBox.scale(pMonitor->scale).round().addExtents(scaledExtentss); if (windowBox.width < 1 || windowBox.height < 1) return; // prevent assert failed From 79ef29d6e0d0a33818cbe90b52f7657d920b3e54 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 22 Dec 2023 23:00:36 +0100 Subject: [PATCH 419/513] renderer: apply scale to wlr after checks ref #4225 --- src/render/Renderer.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index b56c275e..81f243b5 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1718,14 +1718,13 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->customDrmMode = {}; if (pMonitorRule->scale > 0.1) { - wlr_output_set_scale(pMonitor->output, pMonitorRule->scale); pMonitor->scale = pMonitorRule->scale; } else { const auto DEFAULTSCALE = pMonitor->getDefaultScale(); - wlr_output_set_scale(pMonitor->output, DEFAULTSCALE); - pMonitor->scale = DEFAULTSCALE; + pMonitor->scale = DEFAULTSCALE; } + wlr_output_set_scale(pMonitor->output, pMonitor->scale); pMonitor->setScale = pMonitor->scale; wlr_output_set_transform(pMonitor->output, pMonitorRule->transform); @@ -1980,6 +1979,8 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } } + wlr_output_set_scale(pMonitor->output, pMonitor->scale); + // clang-format off static const std::array>, 2> formats{ std::vector>{ /* 10-bit */ From 6b6f3396cfb6cabcf64d21dac773eecbdc5954f0 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 23 Dec 2023 00:09:55 +0100 Subject: [PATCH 420/513] renderer: deny invalid scales and suggest a replacement ref #4225 #3511 --- src/render/Renderer.cpp | 60 ++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 81f243b5..69f9f4b4 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1948,34 +1948,44 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR // invalid scale, will produce fractional pixels. // find the nearest valid. - float searchScale = std::round(pMonitor->scale * 360.0); - bool found = false; + float searchScale = std::round(pMonitor->scale * 360.0); + bool found = false; - for (size_t i = 0; i < 90; ++i) { - double scaleUp = (searchScale + i) / 360.0; - double scaleDown = (searchScale - i) / 360.0; + double scaleZero = searchScale / 360.0; - Vector2D logicalUp = pMonitor->vecPixelSize / scaleUp; - Vector2D logicalDown = pMonitor->vecPixelSize / scaleDown; - - if (logicalUp == logicalUp.round()) { - found = true; - searchScale = scaleUp; - break; - } - if (logicalDown == logicalDown.round()) { - found = true; - searchScale = scaleDown; - break; - } - } - - if (!found) { - Debug::log(ERR, "Invalid scale passed to monitor, {} failed to find a clean divisor", pMonitor->scale); - g_pConfigManager->addParseError("Invalid scale passed to monitor " + pMonitor->szName + ", failed to find a clean divisor"); + Vector2D logicalZero = pMonitor->vecPixelSize / scaleZero; + if (logicalZero == logicalZero.round()) { + pMonitor->scale = scaleZero; } else { - Debug::log(WARN, "Invalid scale ({}) passed to monitor, adjusting to {}", pMonitor->scale, searchScale); - pMonitor->scale = searchScale; + for (size_t i = 1; i < 90; ++i) { + double scaleUp = (searchScale + i) / 360.0; + double scaleDown = (searchScale - i) / 360.0; + + Vector2D logicalUp = pMonitor->vecPixelSize / scaleUp; + Vector2D logicalDown = pMonitor->vecPixelSize / scaleDown; + + if (logicalUp == logicalUp.round()) { + found = true; + searchScale = scaleUp; + break; + } + if (logicalDown == logicalDown.round()) { + found = true; + searchScale = scaleDown; + break; + } + } + + if (!found) { + Debug::log(ERR, "Invalid scale passed to monitor, {} failed to find a clean divisor", pMonitor->scale); + g_pConfigManager->addParseError("Invalid scale passed to monitor " + pMonitor->szName + ", failed to find a clean divisor"); + } else { + Debug::log(ERR, "Invalid scale passed to monitor, {} found suggestion {}", pMonitor->scale, searchScale); + g_pConfigManager->addParseError( + std::format("Invalid scale passed to monitor {}, failed to find a clean divisor. Suggested nearest scale: {:4f}", pMonitor->szName, searchScale)); + } + + pMonitor->scale = pMonitor->getDefaultScale(); } } From 6c8e0f9863d86755d7931a9d6ad920b2049cf6a6 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 23 Dec 2023 00:21:02 +0100 Subject: [PATCH 421/513] config: add debug:disable_scale_checks ref #4225 --- src/config/ConfigManager.cpp | 23 ++++++++++++----------- src/render/Renderer.cpp | 4 +++- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index fb5c7b02..477c3986 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -146,17 +146,18 @@ void CConfigManager::setDefaultVars() { ((CGradientValueData*)configValues["group:groupbar:col.locked_active"].data.get())->reset(0x66ff5500); ((CGradientValueData*)configValues["group:groupbar:col.locked_inactive"].data.get())->reset(0x66775500); - configValues["debug:int"].intValue = 0; - configValues["debug:log_damage"].intValue = 0; - configValues["debug:overlay"].intValue = 0; - configValues["debug:damage_blink"].intValue = 0; - configValues["debug:disable_logs"].intValue = 1; - configValues["debug:disable_time"].intValue = 1; - configValues["debug:enable_stdout_logs"].intValue = 0; - configValues["debug:damage_tracking"].intValue = DAMAGE_TRACKING_FULL; - configValues["debug:manual_crash"].intValue = 0; - configValues["debug:suppress_errors"].intValue = 0; - configValues["debug:watchdog_timeout"].intValue = 5; + configValues["debug:int"].intValue = 0; + configValues["debug:log_damage"].intValue = 0; + configValues["debug:overlay"].intValue = 0; + configValues["debug:damage_blink"].intValue = 0; + configValues["debug:disable_logs"].intValue = 1; + configValues["debug:disable_time"].intValue = 1; + configValues["debug:enable_stdout_logs"].intValue = 0; + configValues["debug:damage_tracking"].intValue = DAMAGE_TRACKING_FULL; + configValues["debug:manual_crash"].intValue = 0; + configValues["debug:suppress_errors"].intValue = 0; + configValues["debug:watchdog_timeout"].intValue = 5; + configValues["debug:disable_scale_checks"].intValue = 0; configValues["decoration:rounding"].intValue = 0; configValues["decoration:blur:enabled"].intValue = 1; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 69f9f4b4..d944a3ec 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1679,6 +1679,8 @@ DAMAGETRACKINGMODES CHyprRenderer::damageTrackingModeFromStr(const std::string& bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorRule, bool force) { + static auto* const PDISABLESCALECHECKS = &g_pConfigManager->getConfigValuePtr("debug:disable_scale_checks")->intValue; + Debug::log(LOG, "Applying monitor rule for {}", pMonitor->szName); pMonitor->activeMonitorRule = *pMonitorRule; @@ -1944,7 +1946,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR pMonitor->vecPixelSize = pMonitor->vecSize; Vector2D logicalSize = pMonitor->vecPixelSize / pMonitor->scale; - if (logicalSize.x != std::round(logicalSize.x) || logicalSize.y != std::round(logicalSize.y)) { + if (!*PDISABLESCALECHECKS && (logicalSize.x != std::round(logicalSize.x) || logicalSize.y != std::round(logicalSize.y))) { // invalid scale, will produce fractional pixels. // find the nearest valid. From cc0516a9aeb36d116f1de06965c827dc91e12073 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 23 Dec 2023 15:49:42 +0100 Subject: [PATCH 422/513] windowrules: minor fixes to onworkspace fixes #4227 --- src/Window.cpp | 2 -- src/config/ConfigManager.cpp | 4 ++-- src/events/Windows.cpp | 2 ++ 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Window.cpp b/src/Window.cpp index 11627d5c..1c4a326d 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -487,8 +487,6 @@ void CWindow::onMap() { "CWindow"); m_vReportedSize = m_vPendingReportedSize; - - g_pCompositor->updateWorkspaceWindows(m_iWorkspaceID); } void CWindow::onBorderAngleAnimEnd(void* ptr) { diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 477c3986..7e4ce769 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1038,9 +1038,9 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s // find workspacepos that isn't onworkspacepos size_t WORKSPACEPOS = std::string::npos; - size_t currentPos = 0; + size_t currentPos = VALUE.find("workspace:"); while (currentPos != std::string::npos) { - if (currentPos > 0 && VALUE[currentPos - 1] != 'n') { + if (currentPos == 0 || VALUE[currentPos - 1] != 'n') { WORKSPACEPOS = currentPos; break; } diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 46427166..ce5103ee 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -643,6 +643,8 @@ void Events::listener_mapWindow(void* owner, void* data) { // fix some xwayland apps that don't behave nicely PWINDOW->m_vReportedSize = PWINDOW->m_vPendingReportedSize; + + g_pCompositor->updateWorkspaceWindows(PWINDOW->m_iWorkspaceID); } void Events::listener_unmapWindow(void* owner, void* data) { From b9c1414f25bfe6972d1996b79566f63c215ec78a Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 23 Dec 2023 16:11:26 +0100 Subject: [PATCH 423/513] border: fix missed translate by offset --- src/render/decorations/CHyprBorderDecoration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index 4b3abd8c..62e3ba7f 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -51,7 +51,7 @@ void CHyprBorderDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& of if (m_bAssignedGeometry.width < m_seExtents.topLeft.x + 1 || m_bAssignedGeometry.height < m_seExtents.topLeft.y + 1) return; - CBox windowBox = assignedBoxGlobal().translate(-pMonitor->vecPosition).expand(-m_pWindow->getRealBorderSize()).scale(pMonitor->scale).round(); + CBox windowBox = assignedBoxGlobal().translate(-pMonitor->vecPosition + offset).expand(-m_pWindow->getRealBorderSize()).scale(pMonitor->scale).round(); if (windowBox.width < 1 || windowBox.height < 1) return; From 5c7e23f86b2a1c79650772dfc8e85cff9475a14c Mon Sep 17 00:00:00 2001 From: dranull <150595692+dranull@users.noreply.github.com> Date: Sat, 23 Dec 2023 19:40:07 +0000 Subject: [PATCH 424/513] shadow: Avoid rounded shadows when rounding is 0 (#4230) --- src/render/decorations/CHyprDropShadowDecoration.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 0f848c61..af4ece0b 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -75,7 +75,8 @@ void CHyprDropShadowDecoration::draw(CMonitor* pMonitor, float a, const Vector2D if (*PSHADOWS != 1) return; // disabled - const auto ROUNDING = m_pWindow->rounding() + m_pWindow->getRealBorderSize(); + const auto ROUNDINGBASE = m_pWindow->rounding(); + const auto ROUNDING = ROUNDINGBASE > 0 ? ROUNDINGBASE + m_pWindow->getRealBorderSize() : 0; const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(m_pWindow->m_iWorkspaceID); const auto WORKSPACEOFFSET = PWORKSPACE && !m_pWindow->m_bPinned ? PWORKSPACE->m_vRenderOffset.vec() : Vector2D(); From d5811283d27619711b031a26db0d04c8d859e6be Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 23 Dec 2023 22:30:49 +0100 Subject: [PATCH 425/513] xdgshell: bump to 6, send suspended states --- src/Compositor.cpp | 11 ++++++++++- src/Compositor.hpp | 1 + src/Window.cpp | 12 ++++++++++++ src/Window.hpp | 4 +++- src/helpers/Monitor.cpp | 6 ++++++ 5 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index e4243a4e..6d892127 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -193,7 +193,7 @@ void CCompositor::initServer() { m_sWLROutputPowerMgr = wlr_output_power_manager_v1_create(m_sWLDisplay); - m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay, 5); + m_sWLRXDGShell = wlr_xdg_shell_create(m_sWLDisplay, 6); m_sWLRCursor = wlr_cursor_create(); wlr_cursor_attach_output_layout(m_sWLRCursor, m_sWLROutputLayout); @@ -2781,3 +2781,12 @@ void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scal void CCompositor::setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform) { wlr_surface_set_preferred_buffer_transform(pSurface, transform); } + +void CCompositor::updateSuspendedStates() { + for (auto& w : g_pCompositor->m_vWindows) { + if (!w->m_bIsMapped) + continue; + + w->setSuspended(w->isHidden() || !g_pHyprRenderer->shouldRenderWindow(w.get())); + } +} diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 8703f3f1..7bedc806 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -208,6 +208,7 @@ class CCompositor { void leaveUnsafeState(); void setPreferredScaleForSurface(wlr_surface* pSurface, double scale); void setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform); + void updateSuspendedStates(); std::string explicitConfigPath; diff --git a/src/Window.cpp b/src/Window.cpp index 1c4a326d..9df8ef69 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -511,6 +511,8 @@ void CWindow::setHidden(bool hidden) { if (hidden && g_pCompositor->m_pLastWindow == this) { g_pCompositor->m_pLastWindow = nullptr; } + + setSuspended(hidden); } bool CWindow::isHidden() { @@ -1007,3 +1009,13 @@ bool CWindow::shouldSendFullscreenState() { const auto MODE = g_pCompositor->getWorkspaceByID(m_iWorkspaceID)->m_efFullscreenMode; return m_bFakeFullscreenState || (m_bIsFullscreen && (MODE == FULLSCREEN_FULL)); } + +void CWindow::setSuspended(bool suspend) { + if (suspend == m_bSuspended) + return; + + if (m_bIsX11) + return; + + wlr_xdg_toplevel_set_suspended(m_uSurface.xdg->toplevel, suspend); +} diff --git a/src/Window.hpp b/src/Window.hpp index 8d5f22e5..bef752fb 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -367,6 +367,7 @@ class CWindow { float rounding(); bool canBeTorn(); bool shouldSendFullscreenState(); + void setSuspended(bool suspend); int getRealBorderSize(); void updateSpecialRenderData(); @@ -392,7 +393,8 @@ class CWindow { private: // For hidden windows and stuff - bool m_bHidden = false; + bool m_bHidden = false; + bool m_bSuspended = false; }; /** diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index c112d07d..ca1318cc 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -565,6 +565,8 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool g_pCompositor->updateFullscreenFadeOnWorkspace(pWorkspace); g_pConfigManager->ensureVRR(this); + + g_pCompositor->updateSuspendedStates(); } void CMonitor::changeWorkspace(const int& id, bool internal) { @@ -590,6 +592,8 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) { else g_pInputManager->refocus(); + g_pCompositor->updateSuspendedStates(); + return; } @@ -631,6 +635,8 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) { g_pEventManager->postEvent(SHyprIPCEvent{"activespecial", pWorkspace->m_szName + "," + szName}); g_pHyprRenderer->damageMonitor(this); + + g_pCompositor->updateSuspendedStates(); } void CMonitor::setSpecialWorkspace(const int& id) { From f013acc6eec60bb2db499aeb009176f932ea3624 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sat, 23 Dec 2023 22:41:42 +0100 Subject: [PATCH 426/513] renderer: add occlusion for special workspaces --- src/render/Renderer.cpp | 33 +++++++++++++++++++++++++++++++++ src/render/Renderer.hpp | 1 + 2 files changed, 34 insertions(+) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index d944a3ec..bb72398b 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -685,11 +685,15 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* // pre window pass g_pHyprOpenGL->preWindowPass(); + setOccludedForMainWorkspace(g_pHyprOpenGL->m_RenderData.damage, pWorkspace); + if (pWorkspace->m_bHasFullscreenWindow) renderWorkspaceWindowsFullscreen(pMonitor, pWorkspace, time); else renderWorkspaceWindows(pMonitor, pWorkspace, time); + g_pHyprOpenGL->m_RenderData.damage = preOccludedDamage; + g_pHyprOpenGL->m_RenderData.renderModif = {}; // and then special @@ -2196,6 +2200,35 @@ void CHyprRenderer::initiateManualCrash() { g_pConfigManager->setInt("debug:damage_tracking", 0); } +void CHyprRenderer::setOccludedForMainWorkspace(CRegion& region, CWorkspace* pWorkspace) { + CRegion rg; + + const auto PMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID); + + if (!PMONITOR->specialWorkspaceID) + return; + + for (auto& w : g_pCompositor->m_vWindows) { + if (!w->m_bIsMapped || w->isHidden() || w->m_iWorkspaceID != PMONITOR->specialWorkspaceID) + continue; + + if (!w->opaque()) + continue; + + const auto ROUNDING = w->rounding() * PMONITOR->scale; + const Vector2D POS = w->m_vRealPosition.vec() + Vector2D{ROUNDING, ROUNDING} - PMONITOR->vecPosition + (w->m_bPinned ? Vector2D{} : pWorkspace->m_vRenderOffset.vec()); + const Vector2D SIZE = w->m_vRealSize.vec() - Vector2D{ROUNDING * 2, ROUNDING * 2}; + + CBox box = {POS.x, POS.y, SIZE.x, SIZE.y}; + + box.scale(PMONITOR->scale); + + rg.add(box); + } + + region.subtract(rg); +} + void CHyprRenderer::setOccludedForBackLayers(CRegion& region, CWorkspace* pWorkspace) { CRegion rg; diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 32815344..d0540a2f 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -61,6 +61,7 @@ class CHyprRenderer { std::tuple getRenderTimes(CMonitor* pMonitor); // avg max min void renderLockscreen(CMonitor* pMonitor, timespec* now); void setOccludedForBackLayers(CRegion& region, CWorkspace* pWorkspace); + void setOccludedForMainWorkspace(CRegion& region, CWorkspace* pWorkspace); // TODO: merge occlusion methods bool canSkipBackBufferClear(CMonitor* pMonitor); void recheckSolitaryForMonitor(CMonitor* pMonitor); void setCursorSurface(wlr_surface* surf, int hotspotX, int hotspotY, bool force = false); From ff75f991a50d9e82bb4ee4cacace551225ef2038 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 24 Dec 2023 13:20:31 +0100 Subject: [PATCH 427/513] compositor: don't block focus if there is no keyboard --- src/Compositor.cpp | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 6d892127..4ea83e89 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1032,20 +1032,17 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) { return; } - const auto KEYBOARD = wlr_seat_get_keyboard(m_sSeat.seat); + if (const auto KEYBOARD = wlr_seat_get_keyboard(m_sSeat.seat); KEYBOARD) { + uint32_t keycodes[WLR_KEYBOARD_KEYS_CAP] = {0}; // TODO: maybe send valid, non-keybind codes? + wlr_seat_keyboard_notify_enter(m_sSeat.seat, pSurface, keycodes, 0, &KEYBOARD->modifiers); - if (!KEYBOARD) - return; - - uint32_t keycodes[WLR_KEYBOARD_KEYS_CAP] = {0}; // TODO: maybe send valid, non-keybind codes? - wlr_seat_keyboard_notify_enter(m_sSeat.seat, pSurface, keycodes, 0, &KEYBOARD->modifiers); - - wlr_seat_keyboard_focus_change_event event = { - .seat = m_sSeat.seat, - .old_surface = m_pLastFocus, - .new_surface = pSurface, - }; - wl_signal_emit_mutable(&m_sSeat.seat->keyboard_state.events.focus_change, &event); + wlr_seat_keyboard_focus_change_event event = { + .seat = m_sSeat.seat, + .old_surface = m_pLastFocus, + .new_surface = pSurface, + }; + wl_signal_emit_mutable(&m_sSeat.seat->keyboard_state.events.focus_change, &event); + } if (pWindowOwner) Debug::log(LOG, "Set keyboard focus to surface {:x}, with {}", (uintptr_t)pSurface, pWindowOwner); From 5aab4a96e3c01cce181b42d51140f7ed4e555d8b Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 24 Dec 2023 15:08:48 +0100 Subject: [PATCH 428/513] dispatchers: add tiled/floating to cyclenext --- src/Compositor.cpp | 16 ++++++++++++++-- src/Compositor.hpp | 4 ++-- src/helpers/VarList.hpp | 9 +++++++++ src/managers/KeybindManager.cpp | 14 +++++++++++--- 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 4ea83e89..a2b11727 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1624,7 +1624,7 @@ CWindow* CCompositor::getWindowInDirection(CWindow* pWindow, char dir) { return nullptr; } -CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow, bool focusableOnly) { +CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow, bool focusableOnly, std::optional floating) { bool gotToWindow = false; for (auto& w : m_vWindows) { if (w.get() != pWindow && !gotToWindow) @@ -1635,11 +1635,17 @@ CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow, bool focusableO continue; } + if (floating.has_value() && w->m_bIsFloating != floating.value()) + continue; + if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_bNoFocus)) return w.get(); } for (auto& w : m_vWindows) { + if (floating.has_value() && w->m_bIsFloating != floating.value()) + continue; + if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_bNoFocus)) return w.get(); } @@ -1647,7 +1653,7 @@ CWindow* CCompositor::getNextWindowOnWorkspace(CWindow* pWindow, bool focusableO return nullptr; } -CWindow* CCompositor::getPrevWindowOnWorkspace(CWindow* pWindow, bool focusableOnly) { +CWindow* CCompositor::getPrevWindowOnWorkspace(CWindow* pWindow, bool focusableOnly, std::optional floating) { bool gotToWindow = false; for (auto& w : m_vWindows | std::views::reverse) { if (w.get() != pWindow && !gotToWindow) @@ -1658,11 +1664,17 @@ CWindow* CCompositor::getPrevWindowOnWorkspace(CWindow* pWindow, bool focusableO continue; } + if (floating.has_value() && w->m_bIsFloating != floating.value()) + continue; + if (w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_bNoFocus)) return w.get(); } for (auto& w : m_vWindows | std::views::reverse) { + if (floating.has_value() && w->m_bIsFloating != floating.value()) + continue; + if (w.get() != pWindow && w->m_iWorkspaceID == pWindow->m_iWorkspaceID && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_bNoFocus)) return w.get(); } diff --git a/src/Compositor.hpp b/src/Compositor.hpp index 7bedc806..ae2d4638 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -165,8 +165,8 @@ class CCompositor { void changeWindowZOrder(CWindow*, bool); void cleanupFadingOut(const int& monid); CWindow* getWindowInDirection(CWindow*, char); - CWindow* getNextWindowOnWorkspace(CWindow*, bool focusableOnly = false); - CWindow* getPrevWindowOnWorkspace(CWindow*, bool focusableOnly = false); + CWindow* getNextWindowOnWorkspace(CWindow*, bool focusableOnly = false, std::optional floating = {}); + CWindow* getPrevWindowOnWorkspace(CWindow*, bool focusableOnly = false, std::optional floating = {}); int getNextAvailableNamedWorkspace(); bool isPointOnAnyMonitor(const Vector2D&); CWindow* getConstraintWindow(SMouse*); diff --git a/src/helpers/VarList.hpp b/src/helpers/VarList.hpp index 8f33f166..d70f2c3f 100644 --- a/src/helpers/VarList.hpp +++ b/src/helpers/VarList.hpp @@ -50,6 +50,15 @@ class CVarList { return m_vArgs.end(); } + bool contains(const std::string& el) { + for (auto& a : m_vArgs) { + if (a == el) + return true; + } + + return false; + } + private: std::vector m_vArgs; }; \ No newline at end of file diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 6aea4e32..d58aa8d8 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1571,10 +1571,18 @@ void CKeybindManager::circleNext(std::string arg) { return; } - if (arg == "last" || arg == "l" || arg == "prev" || arg == "p") - switchToWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow, true)); + CVarList args{arg, 0, 's', true}; + + std::optional floatStatus = {}; + if (args.contains("tile") || args.contains("tiled")) + floatStatus = false; + else if (args.contains("float") || args.contains("floating")) + floatStatus = true; + + if (args.contains("prev") || args.contains("p") || args.contains("last") || args.contains("l")) + switchToWindow(g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow, true, floatStatus)); else - switchToWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow, true)); + switchToWindow(g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow, true, floatStatus)); } void CKeybindManager::focusWindow(std::string regexp) { From b25b06430ba82ebd1977ad75b6cb1b86dd07cb8b Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Sun, 24 Dec 2023 18:29:04 +0000 Subject: [PATCH 429/513] groupbar: add egl context to refreshGroupBarGradients() (#4238) * add egl context to refreshGroupBarGradients() modified: src/render/decorations/CHyprGroupBarDecoration.cpp * don't unsetEGL modified: src/render/decorations/CHyprGroupBarDecoration.cpp --- src/render/decorations/CHyprGroupBarDecoration.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index ae1d76a7..8b4958bc 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -288,6 +288,8 @@ void refreshGroupBarGradients() { static auto* const PGROUPCOLACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_active")->data; static auto* const PGROUPCOLINACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_inactive")->data; + g_pHyprRenderer->makeEGLCurrent(); + if (m_tGradientActive.m_iTexID != 0) { m_tGradientActive.destroyTexture(); m_tGradientInactive.destroyTexture(); From e2d04ae503ffc0c9f98d6ad5177d561f1af14636 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 25 Dec 2023 18:04:00 +0100 Subject: [PATCH 430/513] renderer: add option to blur popups closes #2134 --- src/config/ConfigManager.cpp | 1 + src/helpers/WLClasses.hpp | 5 ++++- src/render/Renderer.cpp | 13 ++++++++++--- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 7e4ce769..c61640cf 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -172,6 +172,7 @@ void CConfigManager::setDefaultVars() { configValues["decoration:blur:vibrancy_darkness"].floatValue = 0.0; configValues["decoration:blur:noise"].floatValue = 0.0117; configValues["decoration:blur:special"].intValue = 0; + configValues["decoration:blur:popups"].intValue = 0; configValues["decoration:active_opacity"].floatValue = 1; configValues["decoration:inactive_opacity"].floatValue = 1; configValues["decoration:fullscreen_opacity"].floatValue = 1; diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp index 644a6bdb..be0fd005 100644 --- a/src/helpers/WLClasses.hpp +++ b/src/helpers/WLClasses.hpp @@ -97,6 +97,8 @@ struct SRenderData { // for calculating UV CWindow* pWindow = nullptr; + + bool popup = false; }; struct SExtensionFindingData { @@ -180,7 +182,8 @@ struct SConstraint { Vector2D getLogicConstraintPos(); Vector2D getLogicConstraintSize(); - bool operator==(const SConstraint& b) const { + // + bool operator==(const SConstraint& b) const { return constraint == b.constraint; } }; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index bb72398b..abd42e46 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -50,8 +50,10 @@ CHyprRenderer::CHyprRenderer() { } static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { - const auto TEXTURE = wlr_surface_get_texture(surface); - const auto RDATA = (SRenderData*)data; + static auto* const PBLURPOPUPS = &g_pConfigManager->getConfigValuePtr("decoration:blur:popups")->intValue; + + const auto TEXTURE = wlr_surface_get_texture(surface); + const auto RDATA = (SRenderData*)data; if (!TEXTURE) return; @@ -134,7 +136,10 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, true); } } else { - g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, true); + if (RDATA->blur && RDATA->popup && *PBLURPOPUPS) + g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding, true); + else + g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, true); } if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) { @@ -544,6 +549,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* renderdata.dontRound = true; // don't round popups renderdata.pMonitor = pMonitor; renderdata.squishOversized = false; // don't squish popups + renderdata.popup = true; if (pWindow->m_sAdditionalConfigData.nearestNeighbor.toUnderlying()) g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; @@ -597,6 +603,7 @@ void CHyprRenderer::renderLayer(SLayerSurface* pLayer, CMonitor* pMonitor, times renderdata.squishOversized = false; // don't squish popups renderdata.dontRound = true; + renderdata.popup = true; wlr_layer_surface_v1_for_each_popup_surface(pLayer->layerSurface, renderSurface, &renderdata); g_pHyprOpenGL->m_pCurrentLayer = nullptr; From 4f99e805b900b72f5e2bed54a1a44d10c8d54771 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Mon, 25 Dec 2023 19:27:25 +0200 Subject: [PATCH 431/513] flake.lock: update --- flake.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 8b7aa952..67aee7c2 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1702312524, - "narHash": "sha256-gkZJRDBUCpTPBvQk25G0B7vfbpEYM5s5OZqghkjZsnE=", + "lastModified": 1703255338, + "narHash": "sha256-Z6wfYJQKmDN9xciTwU3cOiOk+NElxdZwy/FiHctCzjU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a9bf124c46ef298113270b1f84a164865987a91c", + "rev": "6df37dc6a77654682fe9f071c62b4242b5342e04", "type": "github" }, "original": { @@ -95,11 +95,11 @@ ] }, "locked": { - "lastModified": 1702334919, - "narHash": "sha256-ibOZ3TLjqndGMcj2f+07NFwDWoum4IbzF58byZuJJNg=", + "lastModified": 1703514399, + "narHash": "sha256-VRr5Xc4S/VPr/gU3fiOD3vSIL2+GJ+LUrmFTWTwnTz4=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "f5c3576c3b6cb1c31a8dfa3e4113f59bfe40cd71", + "rev": "0a318a7a217a6402b0b705837cd5b50b0e94b31b", "type": "github" }, "original": { From 2c2ff4b61b774915089229ec43d4e05b690d38bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= <123550+andresilva@users.noreply.github.com> Date: Tue, 26 Dec 2023 13:14:12 +0000 Subject: [PATCH 432/513] hyprctl: check only ISDEBUG in version (#3702) --- src/debug/HyprCtl.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 68b74fa7..11f293a5 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -753,10 +753,7 @@ std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) { #ifdef LEGACY_RENDERER result += "legacyrenderer\n"; #endif -#ifndef NDEBUG - result += "debug\n"; -#endif -#ifdef HYPRLAND_DEBUG +#ifndef ISDEBUG result += "debug\n"; #endif #ifdef NO_XWAYLAND @@ -779,10 +776,7 @@ std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) { #ifdef LEGACY_RENDERER result += "\"legacyrenderer\","; #endif -#ifndef NDEBUG - result += "\"debug\","; -#endif -#ifdef HYPRLAND_DEBUG +#ifndef ISDEBUG result += "\"debug\","; #endif #ifdef NO_XWAYLAND From 34b0ce66b3727d5061a3cec2ac96124470b748da Mon Sep 17 00:00:00 2001 From: dranull <150595692+dranull@users.noreply.github.com> Date: Tue, 26 Dec 2023 16:24:31 +0000 Subject: [PATCH 433/513] dwindle: Use window->middle() when cursor is on reserved area (#4253) --- src/Compositor.cpp | 20 +++++++++----------- src/Compositor.hpp | 2 +- src/layout/DwindleLayout.cpp | 15 ++++++++------- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index a2b11727..38304f33 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1723,6 +1723,15 @@ bool CCompositor::isPointOnAnyMonitor(const Vector2D& point) { return false; } +bool CCompositor::isPointOnReservedArea(const Vector2D& point, const CMonitor* pMonitor) { + const auto PMONITOR = pMonitor ? pMonitor : getMonitorFromVector(point); + + const auto XY1 = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; + const auto XY2 = PMONITOR->vecPosition + PMONITOR->vecSize - PMONITOR->vecReservedBottomRight; + + return !VECINRECT(point, XY1.x, XY1.y, XY2.x, XY2.y); +} + void checkFocusSurfaceIter(wlr_surface* pSurface, int x, int y, void* data) { auto pair = (std::pair*)data; pair->second = pair->second || pSurface == pair->first; @@ -2528,17 +2537,6 @@ void CCompositor::forceReportSizesToWindowsOnWorkspace(const int& wid) { } } -bool CCompositor::cursorOnReservedArea() { - const auto PMONITOR = getMonitorFromCursor(); - - const auto XY1 = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; - const auto XY2 = PMONITOR->vecPosition + PMONITOR->vecSize - PMONITOR->vecReservedBottomRight; - - const auto CURSORPOS = g_pInputManager->getMouseCoordsInternal(); - - return !VECINRECT(CURSORPOS, XY1.x, XY1.y, XY2.x, XY2.y); -} - CWorkspace* CCompositor::createNewWorkspace(const int& id, const int& monid, const std::string& name) { const auto NAME = name == "" ? std::to_string(id) : name; auto monID = monid; diff --git a/src/Compositor.hpp b/src/Compositor.hpp index ae2d4638..f954526c 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -169,6 +169,7 @@ class CCompositor { CWindow* getPrevWindowOnWorkspace(CWindow*, bool focusableOnly = false, std::optional floating = {}); int getNextAvailableNamedWorkspace(); bool isPointOnAnyMonitor(const Vector2D&); + bool isPointOnReservedArea(const Vector2D& point, const CMonitor* monitor = nullptr); CWindow* getConstraintWindow(SMouse*); CMonitor* getMonitorInDirection(const char&); void updateAllWindowsAnimatedDecorationValues(); @@ -192,7 +193,6 @@ class CCompositor { void closeWindow(CWindow*); Vector2D parseWindowVectorArgsRelative(const std::string&, const Vector2D&); void forceReportSizesToWindowsOnWorkspace(const int&); - bool cursorOnReservedArea(); CWorkspace* createNewWorkspace(const int&, const int&, const std::string& name = ""); // will be deleted next frame if left empty and unfocused! void renameWorkspace(const int&, const std::string& name = ""); void setActiveMonitor(CMonitor*); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index b30d0fb6..63c2fec2 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -254,10 +254,11 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire const auto MOUSECOORDS = m_vOverrideFocalPoint.value_or(g_pInputManager->getMouseCoordsInternal()); const auto MONFROMCURSOR = g_pCompositor->getMonitorFromVector(MOUSECOORDS); + const auto TARGETCOORDS = PMONITOR->ID == MONFROMCURSOR->ID && g_pCompositor->isPointOnReservedArea(MOUSECOORDS, PMONITOR) ? pWindow->middle() : MOUSECOORDS; if (PMONITOR->ID == MONFROMCURSOR->ID && (PNODE->workspaceID == PMONITOR->activeWorkspace || (g_pCompositor->isWorkspaceSpecial(PNODE->workspaceID) && PMONITOR->specialWorkspaceID)) && !*PUSEACTIVE) { - OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(MOUSECOORDS)); + OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(TARGETCOORDS)); // happens on reserved area if (!OPENINGON && g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID) > 0) @@ -268,7 +269,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID && g_pCompositor->m_pLastWindow->m_bIsMapped) { OPENINGON = getNodeFromWindow(g_pCompositor->m_pLastWindow); } else { - OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(MOUSECOORDS)); + OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindowTiled(TARGETCOORDS)); } if (!OPENINGON && g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID) > 0) @@ -399,15 +400,15 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire const auto br = NEWPARENT->box.pos() + NEWPARENT->box.size(); const auto cc = NEWPARENT->box.pos() + NEWPARENT->box.size() / 2; - if (MOUSECOORDS.inTriangle(tl, tr, cc)) { + if (TARGETCOORDS.inTriangle(tl, tr, cc)) { NEWPARENT->splitTop = true; NEWPARENT->children[0] = PNODE; NEWPARENT->children[1] = OPENINGON; - } else if (MOUSECOORDS.inTriangle(tr, cc, br)) { + } else if (TARGETCOORDS.inTriangle(tr, cc, br)) { NEWPARENT->splitTop = false; NEWPARENT->children[0] = OPENINGON; NEWPARENT->children[1] = PNODE; - } else if (MOUSECOORDS.inTriangle(br, bl, cc)) { + } else if (TARGETCOORDS.inTriangle(br, bl, cc)) { NEWPARENT->splitTop = true; NEWPARENT->children[0] = OPENINGON; NEWPARENT->children[1] = PNODE; @@ -418,9 +419,9 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire } } else if (*PFORCESPLIT == 0 || !pWindow->m_bFirstMap) { if ((SIDEBYSIDE && - VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y + NEWPARENT->box.h)) || + VECINRECT(TARGETCOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w / 2.f, NEWPARENT->box.y + NEWPARENT->box.h)) || (!SIDEBYSIDE && - VECINRECT(MOUSECOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w, NEWPARENT->box.y + NEWPARENT->box.h / 2.f))) { + VECINRECT(TARGETCOORDS, NEWPARENT->box.x, NEWPARENT->box.y / *PWIDTHMULTIPLIER, NEWPARENT->box.x + NEWPARENT->box.w, NEWPARENT->box.y + NEWPARENT->box.h / 2.f))) { // we are hovering over the first node, make PNODE first. NEWPARENT->children[1] = OPENINGON; NEWPARENT->children[0] = PNODE; From bfb4d66c8144a36f2c52530f10ae4bac2ac03b09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= <123550+andresilva@users.noreply.github.com> Date: Tue, 26 Dec 2023 17:16:59 +0000 Subject: [PATCH 434/513] compositor: spawn environment setup with keybind manager (#3722) --- src/Compositor.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 38304f33..c5f54f04 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -516,14 +516,15 @@ void CCompositor::startCompositor() { signal(SIGPIPE, SIG_IGN); - if (m_sWLRSession /* Session-less Hyprland usually means a nest, don't update the env in that case */ && fork() == 0) - execl("/bin/sh", "/bin/sh", "-c", + if (m_sWLRSession /* Session-less Hyprland usually means a nest, don't update the env in that case */) { + const auto CMD = #ifdef USES_SYSTEMD - "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME && hash " - "dbus-update-activation-environment 2>/dev/null && " + "systemctl --user import-environment DISPLAY WAYLAND_DISPLAY HYPRLAND_INSTANCE_SIGNATURE XDG_CURRENT_DESKTOP QT_QPA_PLATFORMTHEME && hash " + "dbus-update-activation-environment 2>/dev/null && " #endif - "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE QT_QPA_PLATFORMTHEME", - nullptr); + "dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE QT_QPA_PLATFORMTHEME"; + g_pKeybindManager->spawn(CMD); + } Debug::log(LOG, "Running on WAYLAND_DISPLAY: {}", m_szWLDisplaySocket); From 9fb50252d3a128466e80bfc2fb67b45dc923ad41 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 26 Dec 2023 19:44:38 +0100 Subject: [PATCH 435/513] special: move floating windows along with the workspace --- src/helpers/Monitor.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index ca1318cc..3b4f4016 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -622,6 +622,22 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) { if (w->m_iWorkspaceID == pWorkspace->m_iID) { w->m_iMonitorID = ID; w->updateSurfaceOutputs(); + + const auto MIDDLE = w->middle(); + if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && w->m_iX11Type != 2) { + // if it's floating and the middle isnt on the current mon, move it to the center + const auto PMONFROMMIDDLE = g_pCompositor->getMonitorFromVector(MIDDLE); + Vector2D pos = w->m_vRealPosition.goalv(); + if (!VECINRECT(MIDDLE, PMONFROMMIDDLE->vecPosition.x, PMONFROMMIDDLE->vecPosition.y, PMONFROMMIDDLE->vecPosition.x + PMONFROMMIDDLE->vecSize.x, + PMONFROMMIDDLE->vecPosition.y + PMONFROMMIDDLE->vecSize.y)) { + // not on any monitor, center + pos = middle() / 2.f - w->m_vRealSize.goalv() / 2.f; + } else + pos = pos - PMONFROMMIDDLE->vecPosition + vecPosition; + + w->m_vRealPosition = pos; + w->m_vPosition = pos; + } } } From 191fa587f4daf9f3bf3e3f791de9e2dc5e95a459 Mon Sep 17 00:00:00 2001 From: Tuur Vanhoutte <4633209+zjeffer@users.noreply.github.com> Date: Tue, 26 Dec 2023 23:47:46 +0100 Subject: [PATCH 436/513] windowrules: add initialTitle and initialClass (#4259) --- src/Window.hpp | 2 ++ src/config/ConfigManager.cpp | 53 +++++++++++++++++++++++++++++------- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/src/Window.hpp b/src/Window.hpp index bef752fb..f9d31ac3 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -151,6 +151,8 @@ struct SWindowRule { bool v2 = false; std::string szTitle; std::string szClass; + std::string szInitialTitle; + std::string szInitialClass; int bX11 = -1; // -1 means "ANY" int bFloating = -1; int bFullscreen = -1; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index c61640cf..f8aef6f5 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1028,14 +1028,16 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s rule.szRule = RULE; rule.szValue = VALUE; - const auto TITLEPOS = VALUE.find("title:"); - const auto CLASSPOS = VALUE.find("class:"); - const auto X11POS = VALUE.find("xwayland:"); - const auto FLOATPOS = VALUE.find("floating:"); - const auto FULLSCREENPOS = VALUE.find("fullscreen:"); - const auto PINNEDPOS = VALUE.find("pinned:"); - const auto FOCUSPOS = VALUE.find("focus:"); - const auto ONWORKSPACEPOS = VALUE.find("onworkspace:"); + const auto TITLEPOS = VALUE.find("title:"); + const auto CLASSPOS = VALUE.find("class:"); + const auto INITIALTITLEPOS = VALUE.find("initialTitle:"); + const auto INITIALCLASSPOS = VALUE.find("initialClass:"); + const auto X11POS = VALUE.find("xwayland:"); + const auto FLOATPOS = VALUE.find("floating:"); + const auto FULLSCREENPOS = VALUE.find("fullscreen:"); + const auto PINNEDPOS = VALUE.find("pinned:"); + const auto FOCUSPOS = VALUE.find("focus:"); + const auto ONWORKSPACEPOS = VALUE.find("onworkspace:"); // find workspacepos that isn't onworkspacepos size_t WORKSPACEPOS = std::string::npos; @@ -1048,8 +1050,9 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s currentPos = VALUE.find("workspace:", currentPos + 1); } - if (TITLEPOS == std::string::npos && CLASSPOS == std::string::npos && X11POS == std::string::npos && FLOATPOS == std::string::npos && FULLSCREENPOS == std::string::npos && - PINNEDPOS == std::string::npos && WORKSPACEPOS == std::string::npos && FOCUSPOS == std::string::npos && ONWORKSPACEPOS == std::string::npos) { + if (TITLEPOS == std::string::npos && CLASSPOS == std::string::npos && INITIALTITLEPOS == std::string::npos && INITIALCLASSPOS == std::string::npos && + X11POS == std::string::npos && FLOATPOS == std::string::npos && FULLSCREENPOS == std::string::npos && PINNEDPOS == std::string::npos && WORKSPACEPOS == std::string::npos && + FOCUSPOS == std::string::npos && ONWORKSPACEPOS == std::string::npos) { Debug::log(ERR, "Invalid rulev2 syntax: {}", VALUE); parseError = "Invalid rulev2 syntax: " + VALUE; return; @@ -1064,6 +1067,10 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s min = TITLEPOS; if (CLASSPOS > pos && CLASSPOS < min) min = CLASSPOS; + if (INITIALTITLEPOS > pos && INITIALTITLEPOS < min) + min = INITIALTITLEPOS; + if (INITIALCLASSPOS > pos && INITIALCLASSPOS < min) + min = INITIALCLASSPOS; if (X11POS > pos && X11POS < min) min = X11POS; if (FLOATPOS > pos && FLOATPOS < min) @@ -1095,6 +1102,12 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s if (TITLEPOS != std::string::npos) rule.szTitle = extract(TITLEPOS + 6); + if (INITIALCLASSPOS != std::string::npos) + rule.szInitialClass = extract(INITIALCLASSPOS + 13); + + if (INITIALTITLEPOS != std::string::npos) + rule.szInitialTitle = extract(INITIALTITLEPOS + 13); + if (X11POS != std::string::npos) rule.bX11 = extract(X11POS + 9) == "1" ? 1 : 0; @@ -1127,6 +1140,12 @@ void CConfigManager::handleWindowRuleV2(const std::string& command, const std::s if (!rule.szTitle.empty() && rule.szTitle != other.szTitle) return false; + if (!rule.szInitialClass.empty() && rule.szInitialClass != other.szInitialClass) + return false; + + if (!rule.szInitialTitle.empty() && rule.szInitialTitle != other.szInitialTitle) + return false; + if (rule.bX11 != -1 && rule.bX11 != other.bX11) return false; @@ -2008,6 +2027,20 @@ std::vector CConfigManager::getMatchingRules(CWindow* pWindow) { continue; } + if (rule.szInitialTitle != "") { + std::regex RULECHECK(rule.szInitialTitle); + + if (!std::regex_search(pWindow->m_szInitialTitle, RULECHECK)) + continue; + } + + if (rule.szInitialClass != "") { + std::regex RULECHECK(rule.szInitialClass); + + if (!std::regex_search(pWindow->m_szInitialClass, RULECHECK)) + continue; + } + if (rule.bX11 != -1) { if (pWindow->m_bIsX11 != rule.bX11) continue; From 7474c819587a138b458e898847fbce93e1dd1d65 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Wed, 27 Dec 2023 11:43:04 +0100 Subject: [PATCH 437/513] pluginapi: Trampoline hooks %rip patching improvements (#4256) --------- Co-authored-by: Jan Beich --- src/plugins/HookSystem.cpp | 140 ++++++++++++++++++++++++------------- src/plugins/HookSystem.hpp | 34 +++++---- 2 files changed, 114 insertions(+), 60 deletions(-) diff --git a/src/plugins/HookSystem.cpp b/src/plugins/HookSystem.cpp index 04b12134..e09fb4f7 100644 --- a/src/plugins/HookSystem.cpp +++ b/src/plugins/HookSystem.cpp @@ -1,5 +1,6 @@ #include "HookSystem.hpp" #include "../debug/Log.hpp" +#include "../helpers/VarList.hpp" #define register #include @@ -19,12 +20,12 @@ CFunctionHook::~CFunctionHook() { unhook(); } -size_t CFunctionHook::getInstructionLenAt(void* start) { +CFunctionHook::SInstructionProbe CFunctionHook::getInstructionLenAt(void* start) { ud_t udis; ud_init(&udis); ud_set_mode(&udis, 64); - ud_set_syntax(&udis, UD_SYN_INTEL); + ud_set_syntax(&udis, UD_SYN_ATT); size_t curOffset = 1; size_t insSize = 0; @@ -41,31 +42,83 @@ size_t CFunctionHook::getInstructionLenAt(void* start) { if (const auto CINS = ud_insn_asm(&udis); CINS) ins = std::string(CINS); - if (!ins.empty() && ins.find("rip") != std::string::npos) { - // todo: support something besides call qword ptr [rip + 0xdeadbeef] - // I don't have an assembler. I don't think udis provides one. Besides, variables might be tricky. - if (((uint8_t*)start)[0] == 0xFF && ((uint8_t*)start)[1] == 0x15) - m_vTrampolineRIPUses.emplace_back(std::make_pair<>((uint64_t)start - (uint64_t)m_pSource, ins)); - else { - Debug::log(ERR, "[CFunctionHook] Cannot hook: unsupported %rip usage: {}", ins); - throw std::runtime_error("unsupported %rip usage"); - } - } - - return insSize; + return {insSize, ins}; } -size_t CFunctionHook::probeMinimumJumpSize(void* start, size_t min) { +CFunctionHook::SInstructionProbe CFunctionHook::probeMinimumJumpSize(void* start, size_t min) { - size_t size = 0; + size_t size = 0; + + std::string instrs = ""; + std::vector sizes; while (size <= min) { // find info about this instruction - size_t insLen = getInstructionLenAt((uint8_t*)start + size); - size += insLen; + auto probe = getInstructionLenAt((uint8_t*)start + size); + sizes.push_back(probe.len); + size += probe.len; + instrs += probe.assembly + "\n"; } - return size; + return {size, instrs, sizes}; +} + +CFunctionHook::SAssembly CFunctionHook::fixInstructionProbeRIPCalls(const SInstructionProbe& probe) { + // analyze the code and fix what we know how to. + uint64_t currentAddress = (uint64_t)m_pSource; + // actually newline + 1 + size_t lastAsmNewline = 0; + std::string assemblyBuilder; + for (auto& len : probe.insSizes) { + + std::string code = probe.assembly.substr(lastAsmNewline, probe.assembly.find("\n", lastAsmNewline) - lastAsmNewline); + if (code.contains("%rip")) { + CVarList tokens{code, 0, 's'}; + size_t plusPresent = tokens[1][0] == '+' ? 1 : 0; + std::string addr = tokens[1].substr(plusPresent, tokens[1].find("(%rip)") - plusPresent); + const uint64_t OFFSET = configStringToInt(addr); + if (OFFSET == 0) + return {}; + const uint64_t DESTINATION = currentAddress + OFFSET + len; + + if (code.starts_with("mov")) { + // mov +0xdeadbeef(%rip), %rax + assemblyBuilder += std::format("movabs $0x{:x}, {}\n", DESTINATION, tokens[2]); + } else if (code.starts_with("call")) { + // call +0xdeadbeef(%rip) + assemblyBuilder += std::format("pushq %rax\nmovabs $0x{:x}, %rax\ncallq *%rax\npopq %rax\n", DESTINATION); + } else if (code.starts_with("lea")) { + // lea 0xdeadbeef(%rip), %rax + assemblyBuilder += std::format("movabs $0x{:x}, {}\n", DESTINATION, tokens[2]); + } else { + return {}; + } + } else { + assemblyBuilder += code + "\n"; + } + + lastAsmNewline = probe.assembly.find("\n", lastAsmNewline) + 1; + currentAddress += len; + } + + std::ofstream ofs("/tmp/hypr/.hookcode.asm", std::ios::trunc); + ofs << assemblyBuilder; + ofs.close(); + execAndGet("cc -x assembler -c /tmp/hypr/.hookcode.asm -o /tmp/hypr/.hookbinary.o && objcopy -O binary -j .text /tmp/hypr/.hookbinary.o /tmp/hypr/.hookbinary2.o"); + if (!std::filesystem::exists("/tmp/hypr/.hookbinary2.o")) { + std::filesystem::remove("/tmp/hypr/.hookcode.asm"); + std::filesystem::remove("/tmp/hypr/.hookbinary.asm"); + return {}; + } + + std::ifstream ifs("/tmp/hypr/.hookbinary2.o", std::ios::binary); + SAssembly returns = {std::vector(std::istreambuf_iterator(ifs), {})}; + ifs.close(); + std::filesystem::remove("/tmp/hypr/.hookcode.asm"); + std::filesystem::remove("/tmp/hypr/.hookbinary.o"); + std::filesystem::remove("/tmp/hypr/.hookbinary2.o"); + + return returns; } bool CFunctionHook::hook() { @@ -85,44 +138,35 @@ bool CFunctionHook::hook() { static constexpr uint8_t POP_RAX[] = {0x58}; // nop static constexpr uint8_t NOP = 0x90; - /* - movabs $0,%rax - callq *%rax - offset for addr: 3 - */ - static constexpr uint8_t CALL_WITH_RAX[] = {0x48, 0xB8, 0xEF, 0xBE, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x10}; - static constexpr size_t CALL_WITH_RAX_ADDRESS_OFFSET = 2; - - // get minimum size to overwrite - size_t HOOKSIZE = 0; + // probe instructions to be trampolin'd + SInstructionProbe probe; try { - HOOKSIZE = probeMinimumJumpSize(m_pSource, sizeof(ABSOLUTE_JMP_ADDRESS) + sizeof(PUSH_RAX) + sizeof(POP_RAX)); + probe = probeMinimumJumpSize(m_pSource, sizeof(ABSOLUTE_JMP_ADDRESS) + sizeof(PUSH_RAX) + sizeof(POP_RAX)); } catch (std::exception& e) { return false; } + const auto PROBEFIXEDASM = fixInstructionProbeRIPCalls(probe); + + if (PROBEFIXEDASM.bytes.size() == 0) { + Debug::log(ERR, "[functionhook] failed, unsupported assembly:\n{}", probe.assembly); + return false; + } + + const size_t HOOKSIZE = PROBEFIXEDASM.bytes.size(); + const size_t ORIGSIZE = probe.len; + // alloc trampoline - const auto TRAMPOLINE_SIZE = sizeof(ABSOLUTE_JMP_ADDRESS) + HOOKSIZE + sizeof(PUSH_RAX) + m_vTrampolineRIPUses.size() * (sizeof(CALL_WITH_RAX) - 6); + const auto TRAMPOLINE_SIZE = sizeof(ABSOLUTE_JMP_ADDRESS) + HOOKSIZE + sizeof(PUSH_RAX); m_pTrampolineAddr = mmap(NULL, TRAMPOLINE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - m_pOriginalBytes = malloc(HOOKSIZE); - memcpy(m_pOriginalBytes, m_pSource, HOOKSIZE); + m_pOriginalBytes = malloc(ORIGSIZE); + memcpy(m_pOriginalBytes, m_pSource, ORIGSIZE); // populate trampoline - memcpy(m_pTrampolineAddr, m_pSource, HOOKSIZE); // first, original func bytes + memcpy(m_pTrampolineAddr, PROBEFIXEDASM.bytes.data(), HOOKSIZE); // first, original but fixed func bytes memcpy((uint8_t*)m_pTrampolineAddr + HOOKSIZE, PUSH_RAX, sizeof(PUSH_RAX)); // then, pushq %rax memcpy((uint8_t*)m_pTrampolineAddr + HOOKSIZE + sizeof(PUSH_RAX), ABSOLUTE_JMP_ADDRESS, sizeof(ABSOLUTE_JMP_ADDRESS)); // then, jump to source - // fix trampoline %rip calls - for (size_t i = 0; i < m_vTrampolineRIPUses.size(); ++i) { - size_t callOffset = i * (sizeof(CALL_WITH_RAX) - 6 /* callq [rip + x] */) + m_vTrampolineRIPUses[i].first; - size_t realCallAddress = (uint64_t)m_pSource + callOffset + 6 + *((uint32_t*)((uint8_t*)m_pSource + callOffset + 2)); - - memmove((uint8_t*)m_pTrampolineAddr + callOffset + sizeof(CALL_WITH_RAX), (uint8_t*)m_pTrampolineAddr + callOffset + 6, TRAMPOLINE_SIZE - callOffset - 6); - memcpy((uint8_t*)m_pTrampolineAddr + callOffset, CALL_WITH_RAX, sizeof(CALL_WITH_RAX)); - - *(uint64_t*)((uint8_t*)m_pTrampolineAddr + callOffset + CALL_WITH_RAX_ADDRESS_OFFSET) = (uint64_t)realCallAddress; - } - // fixup trampoline addr *(uint64_t*)((uint8_t*)m_pTrampolineAddr + TRAMPOLINE_SIZE - sizeof(ABSOLUTE_JMP_ADDRESS) + ABSOLUTE_JMP_ADDRESS_OFFSET) = (uint64_t)((uint8_t*)m_pSource + sizeof(ABSOLUTE_JMP_ADDRESS)); @@ -130,14 +174,14 @@ bool CFunctionHook::hook() { // make jump to hk const auto PAGESIZE = sysconf(_SC_PAGE_SIZE); const uint8_t* PROTSTART = (uint8_t*)m_pSource - ((uint64_t)m_pSource % PAGESIZE); - const size_t PROTLEN = std::ceil((float)(HOOKSIZE + ((uint64_t)m_pSource - (uint64_t)PROTSTART)) / (float)PAGESIZE) * PAGESIZE; + const size_t PROTLEN = std::ceil((float)(ORIGSIZE + ((uint64_t)m_pSource - (uint64_t)PROTSTART)) / (float)PAGESIZE) * PAGESIZE; mprotect((uint8_t*)PROTSTART, PROTLEN, PROT_READ | PROT_WRITE | PROT_EXEC); memcpy((uint8_t*)m_pSource, ABSOLUTE_JMP_ADDRESS, sizeof(ABSOLUTE_JMP_ADDRESS)); // make popq %rax and NOP all remaining memcpy((uint8_t*)m_pSource + sizeof(ABSOLUTE_JMP_ADDRESS), POP_RAX, sizeof(POP_RAX)); size_t currentOp = sizeof(ABSOLUTE_JMP_ADDRESS) + sizeof(POP_RAX); - memset((uint8_t*)m_pSource + currentOp, NOP, HOOKSIZE - currentOp); + memset((uint8_t*)m_pSource + currentOp, NOP, ORIGSIZE - currentOp); // fixup jump addr *(uint64_t*)((uint8_t*)m_pSource + ABSOLUTE_JMP_ADDRESS_OFFSET) = (uint64_t)(m_pDestination); @@ -149,7 +193,7 @@ bool CFunctionHook::hook() { m_pOriginal = m_pTrampolineAddr; m_bActive = true; - m_iHookLen = HOOKSIZE; + m_iHookLen = ORIGSIZE; m_iTrampoLen = TRAMPOLINE_SIZE; return true; diff --git a/src/plugins/HookSystem.hpp b/src/plugins/HookSystem.hpp index 00494733..8714ac32 100644 --- a/src/plugins/HookSystem.hpp +++ b/src/plugins/HookSystem.hpp @@ -22,21 +22,31 @@ class CFunctionHook { void* m_pOriginal = nullptr; private: - void* m_pSource = nullptr; - void* m_pFunctionAddr = nullptr; - void* m_pTrampolineAddr = nullptr; - void* m_pDestination = nullptr; - size_t m_iHookLen = 0; - size_t m_iTrampoLen = 0; - HANDLE m_pOwner = nullptr; - bool m_bActive = false; + void* m_pSource = nullptr; + void* m_pFunctionAddr = nullptr; + void* m_pTrampolineAddr = nullptr; + void* m_pDestination = nullptr; + size_t m_iHookLen = 0; + size_t m_iTrampoLen = 0; + HANDLE m_pOwner = nullptr; + bool m_bActive = false; - std::vector> m_vTrampolineRIPUses; + void* m_pOriginalBytes = nullptr; - void* m_pOriginalBytes = nullptr; + struct SInstructionProbe { + size_t len = 0; + std::string assembly = ""; + std::vector insSizes; + }; - size_t probeMinimumJumpSize(void* start, size_t min); - size_t getInstructionLenAt(void* start); + struct SAssembly { + std::vector bytes; + }; + + SInstructionProbe probeMinimumJumpSize(void* start, size_t min); + SInstructionProbe getInstructionLenAt(void* start); + + SAssembly fixInstructionProbeRIPCalls(const SInstructionProbe& probe); friend class CHookSystem; }; From 1ecd173c7a77b5443473c03e32a119ff5b5a094b Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Wed, 27 Dec 2023 10:43:55 +0000 Subject: [PATCH 438/513] groupbar: remove extra border size from groupbars (#4262) modified: src/render/decorations/CHyprGroupBarDecoration.cpp --- src/render/decorations/CHyprGroupBarDecoration.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 8b4958bc..06e84abb 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -23,7 +23,6 @@ CHyprGroupBarDecoration::CHyprGroupBarDecoration(CWindow* pWindow) : IHyprWindow CHyprGroupBarDecoration::~CHyprGroupBarDecoration() {} SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() { - const int BORDERSIZE = m_pWindow->getRealBorderSize(); static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("group:groupbar:render_titles")->intValue; static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue; @@ -32,7 +31,7 @@ SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() { info.edges = DECORATION_EDGE_TOP; info.priority = 3; info.reserved = true; - info.desiredExtents = {{0, BORDERSIZE + BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0) + 2}, {0, 0}}; + info.desiredExtents = {{0, BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0) + 2}, {0, 0}}; return info; } @@ -83,8 +82,6 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue; static auto* const PGRADIENTS = &g_pConfigManager->getConfigValuePtr("group:groupbar:gradients")->intValue; - const int BORDERSIZE = m_pWindow->getRealBorderSize(); - if (!m_pWindow->m_sSpecialRenderData.decorate) return; @@ -92,7 +89,7 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& m_fBarWidth = (ASSIGNEDBOX.w - BAR_HORIZONTAL_PADDING * (barsToDraw - 1)) / barsToDraw; - const auto DESIREDHEIGHT = BORDERSIZE + BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0) + 2; + const auto DESIREDHEIGHT = BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0) + 2; if (DESIREDHEIGHT != ASSIGNEDBOX.h) g_pDecorationPositioner->repositionDeco(this); From 6cd82d948f93be98d0fe5516722a9228f22315d1 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Wed, 27 Dec 2023 10:44:13 +0000 Subject: [PATCH 439/513] input: don't steal mouseDown from LS (#4260) modified: src/managers/input/InputManager.cpp --- src/managers/input/InputManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index db06de55..157893d5 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -606,7 +606,7 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { const auto mouseCoords = g_pInputManager->getMouseCoordsInternal(); const auto w = g_pCompositor->vectorToWindowIdeal(mouseCoords); - if (w && !w->m_bIsFullscreen && !w->hasPopupAt(mouseCoords)) { + if (w && !w->m_bIsFullscreen && !m_bLastFocusOnLS && !w->hasPopupAt(mouseCoords)) { for (auto& wd : w->m_dWindowDecorations) { if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) continue; From 85d375e8ab4cea0256ff038d2f6340a857e1e1ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= Date: Wed, 27 Dec 2023 12:12:48 +0000 Subject: [PATCH 440/513] flake.lock: update nixpkgs --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 67aee7c2..f7761728 100644 --- a/flake.lock +++ b/flake.lock @@ -25,11 +25,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1703255338, - "narHash": "sha256-Z6wfYJQKmDN9xciTwU3cOiOk+NElxdZwy/FiHctCzjU=", + "lastModified": 1703438236, + "narHash": "sha256-aqVBq1u09yFhL7bj1/xyUeJjzr92fXVvQSSEx6AdB1M=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6df37dc6a77654682fe9f071c62b4242b5342e04", + "rev": "5f64a12a728902226210bf01d25ec6cbb9d9265b", "type": "github" }, "original": { From f86cdcf8d5a9e0150c16fa1ff0d097b81a983792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= Date: Tue, 26 Dec 2023 16:54:07 +0000 Subject: [PATCH 441/513] nix: fix wlroots build --- nix/wlroots.nix | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/nix/wlroots.nix b/nix/wlroots.nix index 005762c3..bd3af688 100644 --- a/nix/wlroots.nix +++ b/nix/wlroots.nix @@ -2,9 +2,6 @@ version, src, wlroots, - hwdata, - libdisplay-info, - libliftoff, enableXWayland ? true, }: wlroots.overrideAttrs (old: { @@ -12,11 +9,5 @@ wlroots.overrideAttrs (old: { pname = "${old.pname}-hyprland"; - buildInputs = - old.buildInputs - ++ [ - hwdata - libliftoff - libdisplay-info - ]; + patches = [ ]; # don't inherit old.patches }) From 2702814a3f054b3ab58c73389635e183cbc0c5a6 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 27 Dec 2023 19:16:57 +0100 Subject: [PATCH 442/513] opengl: add toggleable nvidia_anti_flicker ref #4252 --- src/config/ConfigManager.cpp | 2 ++ src/render/Renderer.cpp | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f8aef6f5..859750b4 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -281,6 +281,8 @@ void CConfigManager::setDefaultVars() { configValues["xwayland:use_nearest_neighbor"].intValue = 1; configValues["xwayland:force_zero_scaling"].intValue = 0; + configValues["opengl:nvidia_anti_flicker"].intValue = 1; + configValues["autogenerated"].intValue = 0; } diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index abd42e46..60aa4e12 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2419,7 +2419,8 @@ bool CHyprRenderer::beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode } void CHyprRenderer::endRender() { - const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor; + const auto PMONITOR = g_pHyprOpenGL->m_RenderData.pMonitor; + static auto* const PNVIDIAANTIFLICKER = &g_pConfigManager->getConfigValuePtr("opengl:nvidia_anti_flicker")->intValue; if (m_eRenderMode != RENDER_MODE_TO_BUFFER_READ_ONLY) g_pHyprOpenGL->end(); @@ -2432,7 +2433,7 @@ void CHyprRenderer::endRender() { if (m_eRenderMode == RENDER_MODE_FULL_FAKE) return; - if (isNvidia()) + if (isNvidia() && *PNVIDIAANTIFLICKER) glFinish(); else glFlush(); From b7e8110a3089d51ae08a3c4fb63a36de1652702c Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 27 Dec 2023 19:23:06 +0100 Subject: [PATCH 443/513] pluginapi: log assembler return --- src/plugins/HookSystem.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/HookSystem.cpp b/src/plugins/HookSystem.cpp index e09fb4f7..abce7a3e 100644 --- a/src/plugins/HookSystem.cpp +++ b/src/plugins/HookSystem.cpp @@ -104,7 +104,9 @@ CFunctionHook::SAssembly CFunctionHook::fixInstructionProbeRIPCalls(const SInstr std::ofstream ofs("/tmp/hypr/.hookcode.asm", std::ios::trunc); ofs << assemblyBuilder; ofs.close(); - execAndGet("cc -x assembler -c /tmp/hypr/.hookcode.asm -o /tmp/hypr/.hookbinary.o && objcopy -O binary -j .text /tmp/hypr/.hookbinary.o /tmp/hypr/.hookbinary2.o"); + std::string ret = execAndGet( + "cc -x assembler -c /tmp/hypr/.hookcode.asm -o /tmp/hypr/.hookbinary.o 2>&1 && objcopy -O binary -j .text /tmp/hypr/.hookbinary.o /tmp/hypr/.hookbinary2.o 2>&1"); + Debug::log(LOG, "[functionhook] assembler returned:\n{}", ret); if (!std::filesystem::exists("/tmp/hypr/.hookbinary2.o")) { std::filesystem::remove("/tmp/hypr/.hookcode.asm"); std::filesystem::remove("/tmp/hypr/.hookbinary.asm"); From e75dafd8b2ab270b2b4b80eb3b79a8f5a4b2943f Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 27 Dec 2023 19:27:15 +0100 Subject: [PATCH 444/513] pluginapi: better wording for plugin function hook errors --- src/plugins/HookSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/HookSystem.cpp b/src/plugins/HookSystem.cpp index abce7a3e..d0a3aeee 100644 --- a/src/plugins/HookSystem.cpp +++ b/src/plugins/HookSystem.cpp @@ -150,7 +150,7 @@ bool CFunctionHook::hook() { const auto PROBEFIXEDASM = fixInstructionProbeRIPCalls(probe); if (PROBEFIXEDASM.bytes.size() == 0) { - Debug::log(ERR, "[functionhook] failed, unsupported assembly:\n{}", probe.assembly); + Debug::log(ERR, "[functionhook] failed, unsupported asm / failed assembling:\n{}", probe.assembly); return false; } From e5eb11ad0423bfdfd4056964ef868e26b2d3c846 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Wed, 27 Dec 2023 20:27:54 +0200 Subject: [PATCH 445/513] Nix: wrap with gcc This ensures the function hook can assemble. --- nix/default.nix | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/nix/default.nix b/nix/default.nix index 4b1be0e2..751457ca 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -132,7 +132,11 @@ assert lib.assertMsg (!hidpiXWayland) "The option `hidpiXWayland` has been remov ln -s ${wlroots}/include/wlr $dev/include/hyprland/wlroots ${lib.optionalString wrapRuntimeDeps '' wrapProgram $out/bin/Hyprland \ - --suffix PATH : ${lib.makeBinPath [binutils pciutils]} + --suffix PATH : ${lib.makeBinPath [ + stdenv.cc + binutils + pciutils + ]} ''} ''; From 07132741bc02631966ca06ed54b55598a8487a5d Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 27 Dec 2023 23:46:56 +0100 Subject: [PATCH 446/513] renderer: use 120 as the denominator in scale checks --- src/render/Renderer.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 60aa4e12..5c827216 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1961,18 +1961,18 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR // invalid scale, will produce fractional pixels. // find the nearest valid. - float searchScale = std::round(pMonitor->scale * 360.0); + float searchScale = std::round(pMonitor->scale * 120.0); bool found = false; - double scaleZero = searchScale / 360.0; + double scaleZero = searchScale / 120.0; Vector2D logicalZero = pMonitor->vecPixelSize / scaleZero; if (logicalZero == logicalZero.round()) { pMonitor->scale = scaleZero; } else { for (size_t i = 1; i < 90; ++i) { - double scaleUp = (searchScale + i) / 360.0; - double scaleDown = (searchScale - i) / 360.0; + double scaleUp = (searchScale + i) / 120.0; + double scaleDown = (searchScale - i) / 120.0; Vector2D logicalUp = pMonitor->vecPixelSize / scaleUp; Vector2D logicalDown = pMonitor->vecPixelSize / scaleDown; @@ -1995,7 +1995,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } else { Debug::log(ERR, "Invalid scale passed to monitor, {} found suggestion {}", pMonitor->scale, searchScale); g_pConfigManager->addParseError( - std::format("Invalid scale passed to monitor {}, failed to find a clean divisor. Suggested nearest scale: {:4f}", pMonitor->szName, searchScale)); + std::format("Invalid scale passed to monitor {}, failed to find a clean divisor. Suggested nearest scale: {:5f}", pMonitor->szName, searchScale)); } pMonitor->scale = pMonitor->getDefaultScale(); From 6a93cee74e8f076068bea1463b95ee0374c50a3a Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 28 Dec 2023 13:36:09 +0100 Subject: [PATCH 447/513] pluginapi: manually detect endbr64 opcodes in function hooks ref #4277 --- src/plugins/HookSystem.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/plugins/HookSystem.cpp b/src/plugins/HookSystem.cpp index d0a3aeee..e52fd749 100644 --- a/src/plugins/HookSystem.cpp +++ b/src/plugins/HookSystem.cpp @@ -93,6 +93,22 @@ CFunctionHook::SAssembly CFunctionHook::fixInstructionProbeRIPCalls(const SInstr } else { return {}; } + } else if (code.contains("invalid")) { + std::vector bytes; + bytes.resize(len); + memcpy(bytes.data(), (std::byte*)currentAddress, len); + if (len == 4 && bytes[0] == 0xF3 && bytes[1] == 0x0F && bytes[2] == 0x1E && bytes[3] == 0xFA) { + // F3 0F 1E FA = endbr64, udis doesn't understand that one + assemblyBuilder += "endbr64\n"; + } else { + // raise error, unknown op + std::string strBytes; + for (auto& b : bytes) { + strBytes += std::format("{:x} ", b); + } + Debug::log(ERR, "[functionhook] unknown bytes: {}", strBytes); + return {}; + } } else { assemblyBuilder += code + "\n"; } From 5f65946c84ed6ba3703e865d9a70f98cbb1ae479 Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Thu, 28 Dec 2023 15:38:16 +0000 Subject: [PATCH 448/513] hyprctl: add decorations (#4275) * add hyprctl decorations modified: hyprctl/main.cpp modified: src/debug/HyprCtl.cpp modified: src/render/decorations/CHyprBorderDecoration.cpp modified: src/render/decorations/CHyprBorderDecoration.hpp modified: src/render/decorations/CHyprDropShadowDecoration.cpp modified: src/render/decorations/CHyprDropShadowDecoration.hpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp modified: src/render/decorations/CHyprGroupBarDecoration.hpp modified: src/render/decorations/IHyprWindowDecoration.cpp modified: src/render/decorations/IHyprWindowDecoration.hpp * fixes modified: hyprctl/main.cpp modified: src/render/decorations/IHyprWindowDecoration.cpp --- hyprctl/main.cpp | 3 ++ src/debug/HyprCtl.cpp | 28 +++++++++++++++++++ .../decorations/CHyprBorderDecoration.cpp | 6 +++- .../decorations/CHyprBorderDecoration.hpp | 4 ++- .../decorations/CHyprDropShadowDecoration.cpp | 4 +++ .../decorations/CHyprDropShadowDecoration.hpp | 4 ++- .../decorations/CHyprGroupBarDecoration.cpp | 4 +++ .../decorations/CHyprGroupBarDecoration.hpp | 2 ++ .../decorations/IHyprWindowDecoration.cpp | 6 +++- .../decorations/IHyprWindowDecoration.hpp | 2 ++ 10 files changed, 59 insertions(+), 4 deletions(-) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 2f0e08ed..7285f5b8 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -31,6 +31,7 @@ commands: binds clients cursorpos + decorations devices dispatch getoption @@ -423,6 +424,8 @@ int main(int argc, char** argv) { request(fullRequest, 1); else if (fullRequest.contains("/keyword")) request(fullRequest, 2); + else if (fullRequest.contains("/decorations")) + request(fullRequest, 1); else if (fullRequest.contains("/hyprpaper")) requestHyprpaper(fullRequest); else if (fullRequest.contains("/layouts")) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 11f293a5..72d3f6b5 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1174,6 +1174,32 @@ std::string dispatchGetOption(std::string request, HyprCtl::eHyprCtlOutputFormat } } +std::string decorationRequest(std::string request, HyprCtl::eHyprCtlOutputFormat format) { + CVarList vars(request, 0, ' '); + const auto PWINDOW = g_pCompositor->getWindowByRegex(vars[1]); + + if (!PWINDOW) + return "none"; + + std::string result = ""; + if (format == HyprCtl::FORMAT_JSON) { + result += "["; + for (auto& wd : PWINDOW->m_dWindowDecorations) { + result += "{\n\"decorationName\": \"" + wd->getDisplayName() + "\",\n\"priority\": " + std::to_string(wd->getPositioningInfo().priority) + "\n},"; + } + + trimTrailingComma(result); + result += "]"; + } else { + result = +"Decoration\tPriority\n"; + for (auto& wd : PWINDOW->m_dWindowDecorations) { + result += wd->getDisplayName() + "\t" + std::to_string(wd->getPositioningInfo().priority) + "\n"; + } + } + + return result; +} + void createOutputIter(wlr_backend* backend, void* data) { const auto DATA = (std::pair*)data; @@ -1415,6 +1441,8 @@ std::string getReply(std::string request) { return dispatchSetCursor(request); else if (request.starts_with("getoption")) return dispatchGetOption(request, format); + else if (request.starts_with("decorations")) + return decorationRequest(request, format); else if (request.starts_with("[[BATCH]]")) return dispatchBatch(request); diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index 62e3ba7f..4e3e824e 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -99,6 +99,10 @@ uint64_t CHyprBorderDecoration::getDecorationFlags() { return *PPARTOFWINDOW && !doesntWantBorders() ? DECORATION_PART_OF_MAIN_WINDOW : 0; } +std::string CHyprBorderDecoration::getDisplayName() { + return "Border"; +} + bool CHyprBorderDecoration::doesntWantBorders() { return !m_pWindow->m_sSpecialRenderData.border || m_pWindow->m_bX11DoesntWantBorders; -} \ No newline at end of file +} diff --git a/src/render/decorations/CHyprBorderDecoration.hpp b/src/render/decorations/CHyprBorderDecoration.hpp index 770d1291..9c0bcc33 100644 --- a/src/render/decorations/CHyprBorderDecoration.hpp +++ b/src/render/decorations/CHyprBorderDecoration.hpp @@ -23,6 +23,8 @@ class CHyprBorderDecoration : public IHyprWindowDecoration { virtual uint64_t getDecorationFlags(); + virtual std::string getDisplayName(); + private: SWindowDecorationExtents m_seExtents; SWindowDecorationExtents m_seReportedExtents; @@ -36,4 +38,4 @@ class CHyprBorderDecoration : public IHyprWindowDecoration { CBox assignedBoxGlobal(); bool doesntWantBorders(); -}; \ No newline at end of file +}; diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index af4ece0b..0e5e9d94 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -30,6 +30,10 @@ uint64_t CHyprDropShadowDecoration::getDecorationFlags() { return DECORATION_NON_SOLID; } +std::string CHyprDropShadowDecoration::getDisplayName() { + return "Drop Shadow"; +} + void CHyprDropShadowDecoration::damageEntire() { static auto* const PSHADOWS = &g_pConfigManager->getConfigValuePtr("decoration:drop_shadow")->intValue; diff --git a/src/render/decorations/CHyprDropShadowDecoration.hpp b/src/render/decorations/CHyprDropShadowDecoration.hpp index 7820a76c..3b389550 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.hpp +++ b/src/render/decorations/CHyprDropShadowDecoration.hpp @@ -23,6 +23,8 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { virtual uint64_t getDecorationFlags(); + virtual std::string getDisplayName(); + private: SWindowDecorationExtents m_seExtents; SWindowDecorationExtents m_seReportedExtents; @@ -34,4 +36,4 @@ class CHyprDropShadowDecoration : public IHyprWindowDecoration { CBox m_bLastWindowBox = {0}; CBox m_bLastWindowBoxWithDecos = {0}; -}; \ No newline at end of file +}; diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 06e84abb..3bc819bf 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -414,6 +414,10 @@ uint64_t CHyprGroupBarDecoration::getDecorationFlags() { return DECORATION_ALLOWS_MOUSE_INPUT; } +std::string CHyprGroupBarDecoration::getDisplayName() { + return "GroupBar"; +} + CBox CHyprGroupBarDecoration::assignedBoxGlobal() { CBox box = m_bAssignedBox; box.translate(g_pDecorationPositioner->getEdgeDefinedPoint(DECORATION_EDGE_TOP, m_pWindow)); diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp index 78edbeae..a0242e2f 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.hpp +++ b/src/render/decorations/CHyprGroupBarDecoration.hpp @@ -45,6 +45,8 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { virtual uint64_t getDecorationFlags(); + virtual std::string getDisplayName(); + private: SWindowDecorationExtents m_seExtents; diff --git a/src/render/decorations/IHyprWindowDecoration.cpp b/src/render/decorations/IHyprWindowDecoration.cpp index 7a4906b5..24acdc47 100644 --- a/src/render/decorations/IHyprWindowDecoration.cpp +++ b/src/render/decorations/IHyprWindowDecoration.cpp @@ -26,4 +26,8 @@ eDecorationLayer IHyprWindowDecoration::getDecorationLayer() { uint64_t IHyprWindowDecoration::getDecorationFlags() { return 0; -} \ No newline at end of file +} + +std::string IHyprWindowDecoration::getDisplayName() { + return "Unknown Decoration"; +} diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp index e0a34016..2203304b 100644 --- a/src/render/decorations/IHyprWindowDecoration.hpp +++ b/src/render/decorations/IHyprWindowDecoration.hpp @@ -56,6 +56,8 @@ class IHyprWindowDecoration { virtual uint64_t getDecorationFlags(); + virtual std::string getDisplayName(); + private: CWindow* m_pWindow = nullptr; From 4f3ee4c645c70a25072545ed8251412290e108f8 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 28 Dec 2023 22:28:58 +0100 Subject: [PATCH 449/513] renderer: add decoration:blur:popups_ignorealpha fixes #4282 --- src/config/ConfigManager.cpp | 63 ++++++++++++++++++------------------ src/render/Renderer.cpp | 14 ++++++-- 2 files changed, 43 insertions(+), 34 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 859750b4..7f603c4a 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -159,37 +159,38 @@ void CConfigManager::setDefaultVars() { configValues["debug:watchdog_timeout"].intValue = 5; configValues["debug:disable_scale_checks"].intValue = 0; - configValues["decoration:rounding"].intValue = 0; - configValues["decoration:blur:enabled"].intValue = 1; - configValues["decoration:blur:size"].intValue = 8; - configValues["decoration:blur:passes"].intValue = 1; - configValues["decoration:blur:ignore_opacity"].intValue = 0; - configValues["decoration:blur:new_optimizations"].intValue = 1; - configValues["decoration:blur:xray"].intValue = 0; - configValues["decoration:blur:contrast"].floatValue = 0.8916; - configValues["decoration:blur:brightness"].floatValue = 1.0; - configValues["decoration:blur:vibrancy"].floatValue = 0.1696; - configValues["decoration:blur:vibrancy_darkness"].floatValue = 0.0; - configValues["decoration:blur:noise"].floatValue = 0.0117; - configValues["decoration:blur:special"].intValue = 0; - configValues["decoration:blur:popups"].intValue = 0; - configValues["decoration:active_opacity"].floatValue = 1; - configValues["decoration:inactive_opacity"].floatValue = 1; - configValues["decoration:fullscreen_opacity"].floatValue = 1; - configValues["decoration:no_blur_on_oversized"].intValue = 0; - configValues["decoration:drop_shadow"].intValue = 1; - configValues["decoration:shadow_range"].intValue = 4; - configValues["decoration:shadow_render_power"].intValue = 3; - configValues["decoration:shadow_ignore_window"].intValue = 1; - configValues["decoration:shadow_offset"].vecValue = Vector2D(); - configValues["decoration:shadow_scale"].floatValue = 1.f; - configValues["decoration:col.shadow"].intValue = 0xee1a1a1a; - configValues["decoration:col.shadow_inactive"].intValue = INT_MAX; - configValues["decoration:dim_inactive"].intValue = 0; - configValues["decoration:dim_strength"].floatValue = 0.5f; - configValues["decoration:dim_special"].floatValue = 0.2f; - configValues["decoration:dim_around"].floatValue = 0.4f; - configValues["decoration:screen_shader"].strValue = STRVAL_EMPTY; + configValues["decoration:rounding"].intValue = 0; + configValues["decoration:blur:enabled"].intValue = 1; + configValues["decoration:blur:size"].intValue = 8; + configValues["decoration:blur:passes"].intValue = 1; + configValues["decoration:blur:ignore_opacity"].intValue = 0; + configValues["decoration:blur:new_optimizations"].intValue = 1; + configValues["decoration:blur:xray"].intValue = 0; + configValues["decoration:blur:contrast"].floatValue = 0.8916; + configValues["decoration:blur:brightness"].floatValue = 1.0; + configValues["decoration:blur:vibrancy"].floatValue = 0.1696; + configValues["decoration:blur:vibrancy_darkness"].floatValue = 0.0; + configValues["decoration:blur:noise"].floatValue = 0.0117; + configValues["decoration:blur:special"].intValue = 0; + configValues["decoration:blur:popups"].intValue = 0; + configValues["decoration:blur:popups_ignorealpha"].floatValue = 0.2; + configValues["decoration:active_opacity"].floatValue = 1; + configValues["decoration:inactive_opacity"].floatValue = 1; + configValues["decoration:fullscreen_opacity"].floatValue = 1; + configValues["decoration:no_blur_on_oversized"].intValue = 0; + configValues["decoration:drop_shadow"].intValue = 1; + configValues["decoration:shadow_range"].intValue = 4; + configValues["decoration:shadow_render_power"].intValue = 3; + configValues["decoration:shadow_ignore_window"].intValue = 1; + configValues["decoration:shadow_offset"].vecValue = Vector2D(); + configValues["decoration:shadow_scale"].floatValue = 1.f; + configValues["decoration:col.shadow"].intValue = 0xee1a1a1a; + configValues["decoration:col.shadow_inactive"].intValue = INT_MAX; + configValues["decoration:dim_inactive"].intValue = 0; + configValues["decoration:dim_strength"].floatValue = 0.5f; + configValues["decoration:dim_special"].floatValue = 0.2f; + configValues["decoration:dim_around"].floatValue = 0.4f; + configValues["decoration:screen_shader"].strValue = STRVAL_EMPTY; configValues["dwindle:pseudotile"].intValue = 0; configValues["dwindle:force_split"].intValue = 0; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 5c827216..ddae866b 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -50,7 +50,8 @@ CHyprRenderer::CHyprRenderer() { } static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) { - static auto* const PBLURPOPUPS = &g_pConfigManager->getConfigValuePtr("decoration:blur:popups")->intValue; + static auto* const PBLURPOPUPS = &g_pConfigManager->getConfigValuePtr("decoration:blur:popups")->intValue; + static auto* const PBLURPOPUPSIGNOREALPHA = &g_pConfigManager->getConfigValuePtr("decoration:blur:popups_ignorealpha")->floatValue; const auto TEXTURE = wlr_surface_get_texture(surface); const auto RDATA = (SRenderData*)data; @@ -136,9 +137,16 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, true); } } else { - if (RDATA->blur && RDATA->popup && *PBLURPOPUPS) + if (RDATA->blur && RDATA->popup && *PBLURPOPUPS) { + + if (*PBLURPOPUPSIGNOREALPHA != 1.f) { + g_pHyprOpenGL->m_RenderData.discardMode |= DISCARD_ALPHA; + g_pHyprOpenGL->m_RenderData.discardOpacity = *PBLURPOPUPSIGNOREALPHA; + } + g_pHyprOpenGL->renderTextureWithBlur(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, surface, rounding, true); - else + g_pHyprOpenGL->m_RenderData.discardMode &= ~DISCARD_ALPHA; + } else g_pHyprOpenGL->renderTexture(TEXTURE, &windowBox, RDATA->fadeAlpha * RDATA->alpha, rounding, true); } From 9fba887cc9c3a8616b43f5778634541099c89c43 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 28 Dec 2023 22:34:12 +0100 Subject: [PATCH 450/513] socket2: emit configreloaded event fixes #4285 --- src/config/ConfigManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 7f603c4a..f77e0324 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1812,6 +1812,7 @@ void CConfigManager::loadConfigLoadVars() { handlePluginLoads(); EMIT_HOOK_EVENT("configReloaded", nullptr); + g_pEventManager->postEvent(SHyprIPCEvent{"configreloaded", ""}); } void CConfigManager::tick() { From cedf5f1fca057351d85560ff72bf2cc6cc609755 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Fri, 29 Dec 2023 00:07:23 +0200 Subject: [PATCH 451/513] CI/Nix: fix build --- .github/workflows/nix-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml index a1ea0f24..2c05d5e2 100644 --- a/.github/workflows/nix-build.yml +++ b/.github/workflows/nix-build.yml @@ -26,4 +26,4 @@ jobs: name: hyprland authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}' - - run: nix build -L ${{ matrix.command }} + - run: nix build .#${{ matrix.package }} -L From 8321d6be46ed2df7dfe7ec142716a7d1a50d2d5e Mon Sep 17 00:00:00 2001 From: dranull <150595692+dranull@users.noreply.github.com> Date: Thu, 28 Dec 2023 22:54:41 +0000 Subject: [PATCH 452/513] internal: Unify input handling on decorations (#4280) * Unify input handling on decorations * Make input methods private * Optional data --- src/Window.cpp | 18 +++++ src/Window.hpp | 1 + src/layout/DwindleLayout.cpp | 12 +-- src/layout/IHyprLayout.cpp | 12 +-- src/layout/MasterLayout.cpp | 12 +-- src/managers/KeybindManager.cpp | 13 +--- src/managers/input/InputManager.cpp | 31 ++------ src/managers/input/InputManager.hpp | 8 ++ .../decorations/CHyprGroupBarDecoration.cpp | 76 +++++++++++++------ .../decorations/CHyprGroupBarDecoration.hpp | 11 +-- .../decorations/IHyprWindowDecoration.cpp | 12 +-- .../decorations/IHyprWindowDecoration.hpp | 7 +- 12 files changed, 104 insertions(+), 109 deletions(-) diff --git a/src/Window.cpp b/src/Window.cpp index 9df8ef69..75a1dc2a 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -222,6 +222,24 @@ void CWindow::removeWindowDeco(IHyprWindowDecoration* deco) { g_pLayoutManager->getCurrentLayout()->recalculateWindow(this); } +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; +} + pid_t CWindow::getPID() { pid_t PID = -1; if (!m_bIsX11) { diff --git a/src/Window.hpp b/src/Window.hpp index f9d31ac3..d5de927b 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -348,6 +348,7 @@ class CWindow { void addWindowDeco(std::unique_ptr deco); void updateWindowDecos(); void removeWindowDeco(IHyprWindowDecoration* deco); + bool checkInputOnDecos(const eInputType, const Vector2D&, std::any = {}); pid_t getPID(); IHyprWindowDecoration* getDecorationByType(eDecorationType); void removeDecorationByType(eDecorationType); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 63c2fec2..53ddb86e 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -316,16 +316,8 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection dire } if (!m_vOverrideFocalPoint && g_pInputManager->m_bWasDraggingWindow) { - for (auto& wd : OPENINGON->pWindow->m_dWindowDecorations) { - if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) - continue; - - if (g_pDecorationPositioner->getWindowDecorationBox(wd.get()).containsPoint(MOUSECOORDS)) { - if (!wd->onEndWindowDragOnDeco(pWindow, MOUSECOORDS)) - return; - break; - } - } + if (OPENINGON->pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_END, MOUSECOORDS, pWindow)) + return; } // if it's a group, add the window diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 0c6d24fd..76f1e796 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -271,16 +271,8 @@ void IHyprLayout::onEndDragWindow() { CWindow* pWindow = g_pCompositor->vectorToWindowIdeal(MOUSECOORDS, DRAGGINGWINDOW); if (pWindow && pWindow->m_bIsFloating) { - for (auto& wd : pWindow->m_dWindowDecorations) { - if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) - continue; - - if (g_pDecorationPositioner->getWindowDecorationBox(wd.get()).containsPoint(MOUSECOORDS)) { - if (!wd->onEndWindowDragOnDeco(DRAGGINGWINDOW, MOUSECOORDS)) - return; - break; - } - } + if (pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_END, MOUSECOORDS, DRAGGINGWINDOW)) + return; if (pWindow->m_sGroupData.pNextWindow && DRAGGINGWINDOW->canBeGroupedInto(pWindow)) { static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("group:insert_after_current")->intValue; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index def03236..65f85691 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -102,16 +102,8 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direc const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); if (g_pInputManager->m_bWasDraggingWindow && OPENINGON) { - for (auto& wd : OPENINGON->pWindow->m_dWindowDecorations) { - if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) - continue; - - if (g_pDecorationPositioner->getWindowDecorationBox(wd.get()).containsPoint(MOUSECOORDS)) { - if (!wd->onEndWindowDragOnDeco(pWindow, MOUSECOORDS)) - return; - break; - } - } + if (OPENINGON->pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_END, MOUSECOORDS, pWindow)) + return; } // if it's a group, add the window diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index d58aa8d8..23478a10 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1840,17 +1840,8 @@ void CKeybindManager::mouse(std::string args) { const auto mouseCoords = g_pInputManager->getMouseCoordsInternal(); CWindow* pWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords); - if (pWindow && !pWindow->m_bIsFullscreen && !pWindow->hasPopupAt(mouseCoords)) { - for (auto& wd : pWindow->m_dWindowDecorations) { - if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) - continue; - - if (g_pDecorationPositioner->getWindowDecorationBox(wd.get()).containsPoint(mouseCoords)) { - wd->onBeginWindowDragOnDeco(mouseCoords); - break; - } - } - } + if (pWindow && !pWindow->m_bIsFullscreen) + pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_START, mouseCoords); if (!g_pInputManager->currentlyDraggedWindow) g_pInputManager->currentlyDraggedWindow = pWindow; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 157893d5..b36b7dbf 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -606,17 +606,8 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { const auto mouseCoords = g_pInputManager->getMouseCoordsInternal(); const auto w = g_pCompositor->vectorToWindowIdeal(mouseCoords); - if (w && !w->m_bIsFullscreen && !m_bLastFocusOnLS && !w->hasPopupAt(mouseCoords)) { - for (auto& wd : w->m_dWindowDecorations) { - if (!(wd->getDecorationFlags() & DECORATION_ALLOWS_MOUSE_INPUT)) - continue; - - if (g_pDecorationPositioner->getWindowDecorationBox(wd.get()).containsPoint(mouseCoords)) { - wd->onMouseButtonOnDeco(mouseCoords, e); - return; - } - } - } + if (w && !w->m_bIsFullscreen && !m_bLastFocusOnLS && w->checkInputOnDecos(INPUT_TYPE_BUTTON, mouseCoords, e)) + return; // clicking on border triggers resize // TODO detect click on LS properly @@ -624,6 +615,7 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { if (w && !w->m_bIsFullscreen) { const CBox real = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; const CBox grab = {real.x - BORDER_GRAB_AREA, real.y - BORDER_GRAB_AREA, real.width + 2 * BORDER_GRAB_AREA, real.height + 2 * BORDER_GRAB_AREA}; + if ((grab.containsPoint(mouseCoords) && (!real.containsPoint(mouseCoords) || w->isInCurvedCorner(mouseCoords.x, mouseCoords.y))) && !w->hasPopupAt(mouseCoords)) { g_pKeybindManager->resizeWithBorder(e); return; @@ -686,8 +678,7 @@ void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) { } void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) { - static auto* const PSCROLLFACTOR = &g_pConfigManager->getConfigValuePtr("input:touchpad:scroll_factor")->floatValue; - static auto* const PGROUPBARSCROLLING = &g_pConfigManager->getConfigValuePtr("group:groupbar:scrolling")->intValue; + static auto* const PSCROLLFACTOR = &g_pConfigManager->getConfigValuePtr("input:touchpad:scroll_factor")->floatValue; auto factor = (*PSCROLLFACTOR <= 0.f || e->source != WLR_AXIS_SOURCE_FINGER ? 1.f : *PSCROLLFACTOR); @@ -702,18 +693,10 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) { return; const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); - const auto pWindow = g_pCompositor->vectorToWindowIdeal(MOUSECOORDS); + const auto PWINDOW = g_pCompositor->vectorToWindowIdeal(MOUSECOORDS); - if (*PGROUPBARSCROLLING && pWindow && !pWindow->m_bIsFullscreen && !pWindow->hasPopupAt(MOUSECOORDS) && pWindow->m_sGroupData.pNextWindow) { - const CBox box = g_pDecorationPositioner->getWindowDecorationBox(pWindow->getDecorationByType(DECORATION_GROUPBAR)); - if (box.containsPoint(MOUSECOORDS)) { - if (e->delta > 0) - pWindow->setGroupCurrent(pWindow->m_sGroupData.pNextWindow); - else - pWindow->setGroupCurrent(pWindow->getGroupPrevious()); - return; - } - } + if (PWINDOW && PWINDOW->checkInputOnDecos(INPUT_TYPE_AXIS, MOUSECOORDS, e)) + return; wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, factor * e->delta, std::round(factor * e->delta_discrete), e->source); } diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 5fa5824e..2b948bb4 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -32,6 +32,14 @@ enum eBorderIconDirection { BORDERICON_DOWN_RIGHT, }; +enum eInputType { + INPUT_TYPE_AXIS = 0, + INPUT_TYPE_BUTTON, + INPUT_TYPE_DRAG_START, + INPUT_TYPE_DRAG_END, + INPUT_TYPE_MOTION +}; + struct STouchData { CWindow* touchFocusWindow = nullptr; SLayerSurface* touchFocusLS = nullptr; diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 3bc819bf..9c785935 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -300,10 +300,35 @@ void refreshGroupBarGradients() { renderGradientTo(m_tGradientLockedInactive, ((CGradientValueData*)PGROUPCOLINACTIVELOCKED->get())->m_vColors[0]); } -bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D& pos) { +bool CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) { + const float BARRELATIVEX = pos.x - assignedBoxGlobal().x; + const int WINDOWINDEX = (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); + if (BARRELATIVEX - (m_fBarWidth + BAR_HORIZONTAL_PADDING) * WINDOWINDEX > m_fBarWidth) + return false; + + CWindow* pWindow = m_pWindow->getGroupWindowByIndex(WINDOWINDEX); + + // hack + g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow); + if (!pWindow->m_bIsFloating) { + const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_bGroupsLocked; + g_pKeybindManager->m_bGroupsLocked = true; + g_pLayoutManager->getCurrentLayout()->onWindowCreated(pWindow); + g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV; + } + + g_pInputManager->currentlyDraggedWindow = pWindow; + + if (!g_pCompositor->isWindowActive(pWindow)) + g_pCompositor->focusWindow(pWindow); + + return true; +} + +bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, CWindow* pDraggedWindow) { if (!pDraggedWindow->canBeGroupedInto(m_pWindow)) - return true; + return false; const float BARRELATIVEX = pos.x - assignedBoxGlobal().x - m_fBarWidth / 2; const int WINDOWINDEX = BARRELATIVEX < 0 ? -1 : (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); @@ -357,12 +382,12 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(CWindow* pDraggedWindow, con if (!pDraggedWindow->getDecorationByType(DECORATION_GROUPBAR)) pDraggedWindow->addWindowDeco(std::make_unique(pDraggedWindow)); - return false; + return true; } -void CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, wlr_pointer_button_event* e) { +bool CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, wlr_pointer_button_event* e) { if (e->state != WLR_BUTTON_PRESSED) - return; + return false; const float BARRELATIVEX = pos.x - assignedBoxGlobal().x; const int WINDOWINDEX = (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); @@ -370,7 +395,7 @@ void CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, wlr_point if (BARRELATIVEX - (m_fBarWidth + BAR_HORIZONTAL_PADDING) * WINDOWINDEX > m_fBarWidth) { if (!g_pCompositor->isWindowActive(m_pWindow)) g_pCompositor->focusWindow(m_pWindow); - return; + return true; } CWindow* pWindow = m_pWindow->getGroupWindowByIndex(WINDOWINDEX); @@ -380,30 +405,33 @@ void CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, wlr_point if (!g_pCompositor->isWindowActive(pWindow)) g_pCompositor->focusWindow(pWindow); + + return true; } -void CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) { - const float BARRELATIVEX = pos.x - assignedBoxGlobal().x; - const int WINDOWINDEX = (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); +bool CHyprGroupBarDecoration::onScrollOnDeco(const Vector2D& pos, wlr_pointer_axis_event* e) { + static auto* const PGROUPBARSCROLLING = &g_pConfigManager->getConfigValuePtr("group:groupbar:scrolling")->intValue; - if (BARRELATIVEX - (m_fBarWidth + BAR_HORIZONTAL_PADDING) * WINDOWINDEX > m_fBarWidth) - return; - - CWindow* pWindow = m_pWindow->getGroupWindowByIndex(WINDOWINDEX); - - // hack - g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow); - if (!pWindow->m_bIsFloating) { - const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_bGroupsLocked; - g_pKeybindManager->m_bGroupsLocked = true; - g_pLayoutManager->getCurrentLayout()->onWindowCreated(pWindow); - g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV; + if (!*PGROUPBARSCROLLING || !m_pWindow->m_sGroupData.pNextWindow) { + return false; } - g_pInputManager->currentlyDraggedWindow = pWindow; + if (e->delta > 0) + m_pWindow->setGroupCurrent(m_pWindow->m_sGroupData.pNextWindow); + else + m_pWindow->setGroupCurrent(m_pWindow->getGroupPrevious()); - if (!g_pCompositor->isWindowActive(pWindow)) - g_pCompositor->focusWindow(pWindow); + return true; +} + +bool CHyprGroupBarDecoration::onInputOnDeco(const eInputType type, const Vector2D& mouseCoords, std::any data) { + switch (type) { + case INPUT_TYPE_AXIS: return onScrollOnDeco(mouseCoords, std::any_cast(data)); + case INPUT_TYPE_BUTTON: return onMouseButtonOnDeco(mouseCoords, std::any_cast(data)); + case INPUT_TYPE_DRAG_START: return onBeginWindowDragOnDeco(mouseCoords); + case INPUT_TYPE_DRAG_END: return onEndWindowDragOnDeco(mouseCoords, std::any_cast(data)); + default: return false; + } } eDecorationLayer CHyprGroupBarDecoration::getDecorationLayer() { diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp index a0242e2f..04f5123b 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.hpp +++ b/src/render/decorations/CHyprGroupBarDecoration.hpp @@ -35,11 +35,7 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { virtual void damageEntire(); - virtual void onBeginWindowDragOnDeco(const Vector2D&); - - virtual bool onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D&); - - virtual void onMouseButtonOnDeco(const Vector2D&, wlr_pointer_button_event*); + virtual bool onInputOnDeco(const eInputType, const Vector2D&, std::any = {}); virtual eDecorationLayer getDecorationLayer(); @@ -63,6 +59,11 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { CBox assignedBoxGlobal(); + bool onBeginWindowDragOnDeco(const Vector2D&); + bool onEndWindowDragOnDeco(const Vector2D&, CWindow*); + bool onMouseButtonOnDeco(const Vector2D&, wlr_pointer_button_event*); + bool onScrollOnDeco(const Vector2D&, wlr_pointer_axis_event*); + struct STitleTexs { // STitleTexs* overriden = nullptr; // TODO: make shit shared in-group to decrease VRAM usage. std::deque> titleTexs; diff --git a/src/render/decorations/IHyprWindowDecoration.cpp b/src/render/decorations/IHyprWindowDecoration.cpp index 24acdc47..973f2700 100644 --- a/src/render/decorations/IHyprWindowDecoration.cpp +++ b/src/render/decorations/IHyprWindowDecoration.cpp @@ -8,16 +8,8 @@ IHyprWindowDecoration::IHyprWindowDecoration(CWindow* pWindow) { IHyprWindowDecoration::~IHyprWindowDecoration() {} -void IHyprWindowDecoration::onBeginWindowDragOnDeco(const Vector2D&) { - ; -} - -bool IHyprWindowDecoration::onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D&) { - return true; -} - -void IHyprWindowDecoration::onMouseButtonOnDeco(const Vector2D&, wlr_pointer_button_event*) { - ; +bool IHyprWindowDecoration::onInputOnDeco(const eInputType, const Vector2D&, std::any) { + return false; } eDecorationLayer IHyprWindowDecoration::getDecorationLayer() { diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp index 2203304b..b457adf4 100644 --- a/src/render/decorations/IHyprWindowDecoration.hpp +++ b/src/render/decorations/IHyprWindowDecoration.hpp @@ -2,6 +2,7 @@ #include "../../defines.hpp" #include "../../helpers/Region.hpp" +#include "../../managers/input/InputManager.hpp" #include "DecorationPositioner.hpp" enum eDecorationType { @@ -46,11 +47,7 @@ class IHyprWindowDecoration { virtual void damageEntire() = 0; // should be ignored by non-absolute decos - virtual void onBeginWindowDragOnDeco(const Vector2D&); // called when the user calls the "movewindow" mouse dispatcher on the deco - - virtual bool onEndWindowDragOnDeco(CWindow* pDraggedWindow, const Vector2D&); // returns true if the window should be placed by the layout - - virtual void onMouseButtonOnDeco(const Vector2D&, wlr_pointer_button_event*); + virtual bool onInputOnDeco(const eInputType, const Vector2D&, std::any = {}); virtual eDecorationLayer getDecorationLayer(); From f771c10d1a6e07406b27727789d0218c7b206439 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 29 Dec 2023 00:04:01 +0100 Subject: [PATCH 453/513] renderer: ignore windowRequestedCursorHide ref #4197, thanks @dtop129 co-authored-by: dtop129 --- src/managers/input/InputManager.cpp | 5 ----- src/render/Renderer.cpp | 2 +- src/render/Renderer.hpp | 1 - 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index b36b7dbf..9aae3e44 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -483,11 +483,6 @@ void CInputManager::onMouseButton(wlr_pointer_button_event* e) { } void CInputManager::processMouseRequest(wlr_seat_pointer_request_set_cursor_event* e) { - if (!e->surface) - g_pHyprRenderer->m_bWindowRequestedCursorHide = true; - else - g_pHyprRenderer->m_bWindowRequestedCursorHide = false; - if (!cursorImageUnlocked()) return; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index ddae866b..6a4a0460 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2165,7 +2165,7 @@ void CHyprRenderer::setCursorHidden(bool hide) { } bool CHyprRenderer::shouldRenderCursor() { - return !m_bCursorHidden && !m_bWindowRequestedCursorHide && m_bCursorHasSurface; + return !m_bCursorHidden && m_bCursorHasSurface; } std::tuple CHyprRenderer::getRenderTimes(CMonitor* pMonitor) { diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index d0540a2f..e236c54a 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -76,7 +76,6 @@ class CHyprRenderer { bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, wlr_buffer* buffer = nullptr, CFramebuffer* fb = nullptr); void endRender(); - bool m_bWindowRequestedCursorHide = false; bool m_bBlockSurfaceFeedback = false; bool m_bRenderingSnapshot = false; CWindow* m_pLastScanout = nullptr; From ddf8e01c1efd3cd3609942a792256fab31d64a76 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 29 Dec 2023 00:17:58 +0100 Subject: [PATCH 454/513] config: don't emit reloaded event before eventManager is created --- src/config/ConfigManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index f77e0324..8a3026e1 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -1812,7 +1812,8 @@ void CConfigManager::loadConfigLoadVars() { handlePluginLoads(); EMIT_HOOK_EVENT("configReloaded", nullptr); - g_pEventManager->postEvent(SHyprIPCEvent{"configreloaded", ""}); + if (g_pEventManager) + g_pEventManager->postEvent(SHyprIPCEvent{"configreloaded", ""}); } void CConfigManager::tick() { From f9c13b614c780c45933440ddecaaa57cc5f1cc12 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 29 Dec 2023 00:26:23 +0100 Subject: [PATCH 455/513] xdg-shell: fix sending of suspended state fixes #4287 --- src/Compositor.cpp | 2 +- src/Window.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index c5f54f04..8a0da27b 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2795,6 +2795,6 @@ void CCompositor::updateSuspendedStates() { if (!w->m_bIsMapped) continue; - w->setSuspended(w->isHidden() || !g_pHyprRenderer->shouldRenderWindow(w.get())); + w->setSuspended(w->isHidden() || !isWorkspaceVisible(w->m_iWorkspaceID)); } } diff --git a/src/Window.cpp b/src/Window.cpp index 75a1dc2a..debacde0 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -1036,4 +1036,5 @@ void CWindow::setSuspended(bool suspend) { return; wlr_xdg_toplevel_set_suspended(m_uSurface.xdg->toplevel, suspend); + m_bSuspended = suspend; } From 9242b033175cfa59796cbf3039dcc41ef4241c11 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 29 Dec 2023 10:24:56 +0100 Subject: [PATCH 456/513] internal: minor include fixes and missed format --- src/SharedDefs.hpp | 8 ++++++++ src/managers/input/InputManager.hpp | 8 -------- src/render/Renderer.hpp | 14 +++++++------- src/render/decorations/IHyprWindowDecoration.hpp | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/SharedDefs.hpp b/src/SharedDefs.hpp index 4b1524b3..da7f6938 100644 --- a/src/SharedDefs.hpp +++ b/src/SharedDefs.hpp @@ -24,6 +24,14 @@ enum eRenderStage { RENDER_POST_WINDOW, /* After rendering a window (any pass) */ }; +enum eInputType { + INPUT_TYPE_AXIS = 0, + INPUT_TYPE_BUTTON, + INPUT_TYPE_DRAG_START, + INPUT_TYPE_DRAG_END, + INPUT_TYPE_MOTION +}; + struct SCallbackInfo { bool cancelled = false; /* on cancellable events, will cancel the event. */ }; diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 2b948bb4..5fa5824e 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -32,14 +32,6 @@ enum eBorderIconDirection { BORDERICON_DOWN_RIGHT, }; -enum eInputType { - INPUT_TYPE_AXIS = 0, - INPUT_TYPE_BUTTON, - INPUT_TYPE_DRAG_START, - INPUT_TYPE_DRAG_END, - INPUT_TYPE_MOTION -}; - struct STouchData { CWindow* touchFocusWindow = nullptr; SLayerSurface* touchFocusLS = nullptr; diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index e236c54a..bc914558 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -76,13 +76,13 @@ class CHyprRenderer { bool beginRender(CMonitor* pMonitor, CRegion& damage, eRenderMode mode = RENDER_MODE_NORMAL, wlr_buffer* buffer = nullptr, CFramebuffer* fb = nullptr); void endRender(); - bool m_bBlockSurfaceFeedback = false; - bool m_bRenderingSnapshot = false; - CWindow* m_pLastScanout = nullptr; - CMonitor* m_pMostHzMonitor = nullptr; - bool m_bDirectScanoutBlocked = false; - bool m_bSoftwareCursorsLocked = false; - bool m_bTearingEnvSatisfied = false; + bool m_bBlockSurfaceFeedback = false; + bool m_bRenderingSnapshot = false; + CWindow* m_pLastScanout = nullptr; + CMonitor* m_pMostHzMonitor = nullptr; + bool m_bDirectScanoutBlocked = false; + bool m_bSoftwareCursorsLocked = false; + bool m_bTearingEnvSatisfied = false; DAMAGETRACKINGMODES damageTrackingModeFromStr(const std::string&); diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp index b457adf4..d3d1a5dd 100644 --- a/src/render/decorations/IHyprWindowDecoration.hpp +++ b/src/render/decorations/IHyprWindowDecoration.hpp @@ -1,8 +1,8 @@ #pragma once +#include #include "../../defines.hpp" #include "../../helpers/Region.hpp" -#include "../../managers/input/InputManager.hpp" #include "DecorationPositioner.hpp" enum eDecorationType { From 78f9ba9fdd7e258747b862ca2ae7d4cf5335f4ed Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 29 Dec 2023 10:37:58 +0100 Subject: [PATCH 457/513] makefile: add symbolic link for lowercase binary name ref #4272 --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 9e9d7afc..a0b00259 100644 --- a/Makefile +++ b/Makefile @@ -42,6 +42,7 @@ install: chmod 755 ${PREFIX}/bin/Hyprland chmod 755 ${PREFIX}/bin/hyprctl chmod 755 ${PREFIX}/bin/hyprpm + ln -s -r ${PREFIX}/bin/Hyprland ${PREFIX}/bin/hyprland if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi mkdir -p ${PREFIX}/share/hyprland cp ./assets/wall_* ${PREFIX}/share/hyprland From 5f8e4068e51480791dbccbe48e86910e9b3cc881 Mon Sep 17 00:00:00 2001 From: dranull <150595692+dranull@users.noreply.github.com> Date: Fri, 29 Dec 2023 23:38:12 +0000 Subject: [PATCH 458/513] groupbar: Middle click on groupbar to close tab (#4297) * Prevent window swapping when the head is removed * Bring floating windows to top when selected * Allow clicks on gropubar in fullscreen 1 * Close window on groupbar with middle click --- src/layout/IHyprLayout.cpp | 6 ++--- src/managers/input/InputManager.cpp | 2 +- .../decorations/CHyprGroupBarDecoration.cpp | 24 +++++++++++++++---- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 76f1e796..6a03ac80 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -36,15 +36,15 @@ void IHyprLayout::onWindowRemoved(CWindow* pWindow) { const auto WINDOWISVISIBLE = pWindow->getGroupCurrent() == pWindow; if (WINDOWISVISIBLE) - PWINDOWPREV->setGroupCurrent(PWINDOWPREV); + PWINDOWPREV->setGroupCurrent(pWindow->m_sGroupData.head ? pWindow->m_sGroupData.pNextWindow : PWINDOWPREV); PWINDOWPREV->m_sGroupData.pNextWindow = pWindow->m_sGroupData.pNextWindow; pWindow->m_sGroupData.pNextWindow = nullptr; if (pWindow->m_sGroupData.head) { - std::swap(PWINDOWPREV->m_sGroupData.head, pWindow->m_sGroupData.head); - std::swap(PWINDOWPREV->m_sGroupData.locked, pWindow->m_sGroupData.locked); + std::swap(PWINDOWPREV->m_sGroupData.pNextWindow->m_sGroupData.head, pWindow->m_sGroupData.head); + std::swap(PWINDOWPREV->m_sGroupData.pNextWindow->m_sGroupData.locked, pWindow->m_sGroupData.locked); } if (pWindow == m_pLastTiledWindow) diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 9aae3e44..78058a8a 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -601,7 +601,7 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { const auto mouseCoords = g_pInputManager->getMouseCoordsInternal(); const auto w = g_pCompositor->vectorToWindowIdeal(mouseCoords); - if (w && !w->m_bIsFullscreen && !m_bLastFocusOnLS && w->checkInputOnDecos(INPUT_TYPE_BUTTON, mouseCoords, e)) + if (w && !m_bLastFocusOnLS && w->checkInputOnDecos(INPUT_TYPE_BUTTON, mouseCoords, e)) return; // clicking on border triggers resize diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 9c785935..cbd7a73f 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -386,12 +386,28 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, CWindow } bool CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, wlr_pointer_button_event* e) { - if (e->state != WLR_BUTTON_PRESSED) - return false; + if (m_pWindow->m_bIsFullscreen && g_pCompositor->getWorkspaceByID(m_pWindow->m_iWorkspaceID)->m_efFullscreenMode == FULLSCREEN_FULL) + return true; const float BARRELATIVEX = pos.x - assignedBoxGlobal().x; const int WINDOWINDEX = (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); + // close window on middle click + if (e->button == 274) { + static Vector2D pressedCursorPos; + + if (e->state == WLR_BUTTON_PRESSED) + pressedCursorPos = pos; + else if (e->state == WLR_BUTTON_RELEASED && pressedCursorPos == pos) + g_pXWaylandManager->sendCloseWindow(m_pWindow->getGroupWindowByIndex(WINDOWINDEX)); + + return true; + } + + if (e->state != WLR_BUTTON_PRESSED) + return true; + + // click on padding if (BARRELATIVEX - (m_fBarWidth + BAR_HORIZONTAL_PADDING) * WINDOWINDEX > m_fBarWidth) { if (!g_pCompositor->isWindowActive(m_pWindow)) g_pCompositor->focusWindow(m_pWindow); @@ -403,8 +419,8 @@ bool CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, wlr_point if (pWindow != m_pWindow) pWindow->setGroupCurrent(pWindow); - if (!g_pCompositor->isWindowActive(pWindow)) - g_pCompositor->focusWindow(pWindow); + if (pWindow->m_bIsFloating) + g_pCompositor->changeWindowZOrder(pWindow, 1); return true; } From 2ad2e1d5f5feaf1b7dd65dc162d16547f6b0b20f Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Sat, 30 Dec 2023 14:18:53 +0000 Subject: [PATCH 459/513] groupbar: add enabling groupbar and setting priority (#4299) --- src/Compositor.cpp | 1 + src/Window.cpp | 6 ++++ src/Window.hpp | 1 + src/config/ConfigManager.cpp | 6 ++++ .../decorations/CHyprGroupBarDecoration.cpp | 32 ++++++++++++++----- .../decorations/DecorationPositioner.cpp | 2 +- 6 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 8a0da27b..26bd56c4 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2629,6 +2629,7 @@ void CCompositor::moveWindowToWorkspaceSafe(CWindow* pWindow, CWorkspace* pWorks pWindow->moveToWorkspace(pWorkspace->m_iID); pWindow->updateToplevel(); pWindow->updateDynamicRules(); + pWindow->uncacheWindowDecos(); if (!pWindow->m_bIsFloating) { g_pLayoutManager->getCurrentLayout()->onWindowRemovedTiling(pWindow); diff --git a/src/Window.cpp b/src/Window.cpp index debacde0..01b58253 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -222,6 +222,12 @@ void CWindow::removeWindowDeco(IHyprWindowDecoration* deco) { g_pLayoutManager->getCurrentLayout()->recalculateWindow(this); } +void CWindow::uncacheWindowDecos() { + for (auto& wd : m_dWindowDecorations) { + g_pDecorationPositioner->uncacheDecoration(wd.get()); + } +} + bool CWindow::checkInputOnDecos(const eInputType type, const Vector2D& mouseCoords, std::any data) { if (type != INPUT_TYPE_DRAG_END && hasPopupAt(mouseCoords)) return false; diff --git a/src/Window.hpp b/src/Window.hpp index d5de927b..559e4c90 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -348,6 +348,7 @@ class CWindow { void addWindowDeco(std::unique_ptr deco); void updateWindowDecos(); void removeWindowDeco(IHyprWindowDecoration* deco); + void uncacheWindowDecos(); bool checkInputOnDecos(const eInputType, const Vector2D&, std::any = {}); pid_t getPID(); IHyprWindowDecoration* getDecorationByType(eDecorationType); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 8a3026e1..ee198ded 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -134,9 +134,11 @@ void CConfigManager::setDefaultVars() { configValues["group:insert_after_current"].intValue = 1; configValues["group:focus_removed_window"].intValue = 1; + configValues["group:groupbar:enabled"].intValue = 1; configValues["group:groupbar:font_family"].strValue = "Sans"; configValues["group:groupbar:font_size"].intValue = 8; configValues["group:groupbar:gradients"].intValue = 1; + configValues["group:groupbar:priority"].intValue = 3; configValues["group:groupbar:render_titles"].intValue = 1; configValues["group:groupbar:scrolling"].intValue = 1; configValues["group:groupbar:text_color"].intValue = 0xffffffff; @@ -1730,6 +1732,10 @@ void CConfigManager::loadConfigLoadVars() { ifs.close(); } + for (auto& w : g_pCompositor->m_vWindows) { + w->uncacheWindowDecos(); + } + for (auto& m : g_pCompositor->m_vMonitors) g_pLayoutManager->getCurrentLayout()->recalculateMonitor(m->ID); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index cbd7a73f..33ecff6a 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -15,8 +15,11 @@ constexpr int BAR_TEXT_PAD = 2; constexpr int BAR_HORIZONTAL_PADDING = 2; CHyprGroupBarDecoration::CHyprGroupBarDecoration(CWindow* pWindow) : IHyprWindowDecoration(pWindow) { - m_pWindow = pWindow; - if (m_tGradientActive.m_iTexID == 0) + static auto* const PGRADIENTS = &g_pConfigManager->getConfigValuePtr("group:groupbar:enabled")->intValue; + static auto* const PENABLED = &g_pConfigManager->getConfigValuePtr("group:groupbar:gradients")->intValue; + m_pWindow = pWindow; + + if (m_tGradientActive.m_iTexID == 0 && *PENABLED && *PGRADIENTS) refreshGroupBarGradients(); } @@ -25,13 +28,19 @@ CHyprGroupBarDecoration::~CHyprGroupBarDecoration() {} SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() { static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("group:groupbar:render_titles")->intValue; static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue; + static auto* const PENABLED = &g_pConfigManager->getConfigValuePtr("group:groupbar:enabled")->intValue; SDecorationPositioningInfo info; - info.policy = DECORATION_POSITION_STICKY; - info.edges = DECORATION_EDGE_TOP; - info.priority = 3; - info.reserved = true; - info.desiredExtents = {{0, BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0) + 2}, {0, 0}}; + info.policy = DECORATION_POSITION_STICKY; + info.edges = DECORATION_EDGE_TOP; + info.priority = g_pConfigManager->getConfigValuePtr("group:groupbar:priority")->intValue; + info.reserved = true; + + if (*PENABLED && m_pWindow->m_sSpecialRenderData.decorate) + info.desiredExtents = {{0, BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0) + 2}, {0, 0}}; + else + info.desiredExtents = {{0, 0}, {0, 0}}; + return info; } @@ -78,11 +87,12 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& // get how many bars we will draw int barsToDraw = m_dwGroupMembers.size(); + static auto* const PENABLED = &g_pConfigManager->getConfigValuePtr("group:groupbar:enabled")->intValue; static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("group:groupbar:render_titles")->intValue; static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue; static auto* const PGRADIENTS = &g_pConfigManager->getConfigValuePtr("group:groupbar:gradients")->intValue; - if (!m_pWindow->m_sSpecialRenderData.decorate) + if (!*PENABLED || !m_pWindow->m_sSpecialRenderData.decorate) return; const auto ASSIGNEDBOX = assignedBoxGlobal(); @@ -280,6 +290,9 @@ void renderGradientTo(CTexture& tex, const CColor& grad) { } void refreshGroupBarGradients() { + static auto* const PGRADIENTS = &g_pConfigManager->getConfigValuePtr("group:groupbar:enabled")->intValue; + static auto* const PENABLED = &g_pConfigManager->getConfigValuePtr("group:groupbar:gradients")->intValue; + static auto* const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.active")->data; static auto* const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.inactive")->data; static auto* const PGROUPCOLACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_active")->data; @@ -294,6 +307,9 @@ void refreshGroupBarGradients() { m_tGradientLockedInactive.destroyTexture(); } + if (!*PENABLED || !*PGRADIENTS) + return; + renderGradientTo(m_tGradientActive, ((CGradientValueData*)PGROUPCOLACTIVE->get())->m_vColors[0]); renderGradientTo(m_tGradientInactive, ((CGradientValueData*)PGROUPCOLINACTIVE->get())->m_vColors[0]); renderGradientTo(m_tGradientLockedActive, ((CGradientValueData*)PGROUPCOLACTIVELOCKED->get())->m_vColors[0]); diff --git a/src/render/decorations/DecorationPositioner.cpp b/src/render/decorations/DecorationPositioner.cpp index bdf37e58..e19c361b 100644 --- a/src/render/decorations/DecorationPositioner.cpp +++ b/src/render/decorations/DecorationPositioner.cpp @@ -370,4 +370,4 @@ CBox CDecorationPositioner::getWindowDecorationBox(IHyprWindowDecoration* deco) CBox box = DATA->lastReply.assignedGeometry; box.translate(getEdgeDefinedPoint(DATA->positioningInfo.edges, deco->m_pWindow)); return box; -} \ No newline at end of file +} From 33fe3a2e7fcb84e671bc7b5bc5fabcafb8fc1832 Mon Sep 17 00:00:00 2001 From: zakk4223 Date: Sat, 30 Dec 2023 09:19:53 -0500 Subject: [PATCH 460/513] hyprpm: Make sure we're in git repo before getting new hash (#4303) --- hyprpm/src/core/PluginManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index e28637fd..3c091242 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -550,7 +550,7 @@ bool CPluginManager::updatePlugins(bool forceUpdateAll) { newrepo.plugins.clear(); execAndGet( "cd /tmp/hyprpm/update/ && git pull --recurse-submodules && git reset --hard --recurse-submodules"); // repo hash in the state.toml has to match head and not any pin - std::string repohash = execAndGet("git rev-parse HEAD"); + std::string repohash = execAndGet("cd /tmp/hyprpm/update && git rev-parse HEAD"); if (repohash.length() > 0) repohash.pop_back(); newrepo.hash = repohash; @@ -721,4 +721,4 @@ std::string CPluginManager::headerError(const eHeadersErrors err) { } return std::string{Colors::RED} + "✖" + Colors::RESET + " Unknown header error. Please run hyprpm update to fix those.\n"; -} \ No newline at end of file +} From 94d6b2d2c12663efe90f6d0410528b0d7bcc671e Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Sat, 30 Dec 2023 15:59:01 +0000 Subject: [PATCH 461/513] deco: fix missing border on togglefloating (#4305) modified: src/managers/KeybindManager.cpp --- src/managers/KeybindManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 23478a10..fc3fcf0d 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -751,6 +751,7 @@ void CKeybindManager::toggleActiveFloating(std::string args) { while (curr != PCURRENT) { curr->m_bIsFloating = PCURRENT->m_bIsFloating; curr->updateDynamicRules(); + curr->updateSpecialRenderData(); curr = curr->m_sGroupData.pNextWindow; } } else { From b5b025a1ed6cfa2b94ad0eff38a247223edd95bb Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 31 Dec 2023 13:11:20 +0100 Subject: [PATCH 462/513] renderer: use nearest_neighbor for misaligned fractional-scale surfaces ref #4225 --- src/render/Renderer.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 6a4a0460..a6d58866 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -53,8 +53,9 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) static auto* const PBLURPOPUPS = &g_pConfigManager->getConfigValuePtr("decoration:blur:popups")->intValue; static auto* const PBLURPOPUPSIGNOREALPHA = &g_pConfigManager->getConfigValuePtr("decoration:blur:popups_ignorealpha")->floatValue; - const auto TEXTURE = wlr_surface_get_texture(surface); - const auto RDATA = (SRenderData*)data; + const auto TEXTURE = wlr_surface_get_texture(surface); + const auto RDATA = (SRenderData*)data; + const auto INTERACTIVERESIZEINPROGRESS = RDATA->pWindow && g_pInputManager->currentlyDraggedWindow == RDATA->pWindow && g_pInputManager->dragMode == MBIND_RESIZE; if (!TEXTURE) return; @@ -72,9 +73,8 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) auto* const PSURFACE = CWLSurface::surfaceFromWlr(surface); if (PSURFACE && !PSURFACE->m_bFillIgnoreSmall && PSURFACE->small() /* guarantees m_pOwner */) { - const auto CORRECT = PSURFACE->correctSmallVec(); - const auto SIZE = PSURFACE->getViewporterCorrectedSize(); - const auto INTERACTIVERESIZEINPROGRESS = g_pInputManager->currentlyDraggedWindow == PSURFACE->m_pOwner && g_pInputManager->dragMode == MBIND_RESIZE; + const auto CORRECT = PSURFACE->correctSmallVec(); + const auto SIZE = PSURFACE->getViewporterCorrectedSize(); if (!INTERACTIVERESIZEINPROGRESS) { windowBox.x += CORRECT.x; @@ -112,6 +112,15 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) windowBox.scale(RDATA->pMonitor->scale); windowBox.round(); + // check for fractional scale surfaces misaligning the buffer size + // in those cases it's better to just force nearest neighbor + // as long as the window is not animated. During those it'd look weird + const auto NEARESTNEIGHBORSET = g_pHyprOpenGL->m_RenderData.useNearestNeighbor; + if (std::floor(RDATA->pMonitor->scale) != RDATA->pMonitor->scale /* Fractional */ && surface->current.scale == 1 /* fs protocol */ && + windowBox.size() != Vector2D{surface->current.buffer_width, surface->current.buffer_height} /* misaligned */ && + (!RDATA->pWindow || (!RDATA->pWindow->m_vRealSize.isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */) + g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; + float rounding = RDATA->rounding; rounding -= 1; // to fix a border issue @@ -157,9 +166,10 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) g_pHyprOpenGL->blend(true); - // reset the UV, we might've set it above + // reset props g_pHyprOpenGL->m_RenderData.primarySurfaceUVTopLeft = Vector2D(-1, -1); g_pHyprOpenGL->m_RenderData.primarySurfaceUVBottomRight = Vector2D(-1, -1); + g_pHyprOpenGL->m_RenderData.useNearestNeighbor = NEARESTNEIGHBORSET; } bool CHyprRenderer::shouldRenderWindow(CWindow* pWindow, CMonitor* pMonitor, CWorkspace* pWorkspace) { From 46997a764304366d772456c20b1c719960927aa7 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 31 Dec 2023 13:54:24 +0100 Subject: [PATCH 463/513] renderer: fix auto scale detection with fractional ref #4225 --- src/render/Renderer.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index a6d58866..88320139 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1747,10 +1747,12 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR // Needed in case we are switching from a custom modeline to a standard mode pMonitor->customDrmMode = {}; + bool autoScale = false; if (pMonitorRule->scale > 0.1) { pMonitor->scale = pMonitorRule->scale; } else { + autoScale = true; const auto DEFAULTSCALE = pMonitor->getDefaultScale(); pMonitor->scale = DEFAULTSCALE; } @@ -2008,15 +2010,22 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } if (!found) { - Debug::log(ERR, "Invalid scale passed to monitor, {} failed to find a clean divisor", pMonitor->scale); - g_pConfigManager->addParseError("Invalid scale passed to monitor " + pMonitor->szName + ", failed to find a clean divisor"); + if (autoScale) + pMonitor->scale = std::round(scaleZero); + else { + Debug::log(ERR, "Invalid scale passed to monitor, {} failed to find a clean divisor", pMonitor->scale); + g_pConfigManager->addParseError("Invalid scale passed to monitor " + pMonitor->szName + ", failed to find a clean divisor"); + pMonitor->scale = pMonitor->getDefaultScale(); + } } else { - Debug::log(ERR, "Invalid scale passed to monitor, {} found suggestion {}", pMonitor->scale, searchScale); - g_pConfigManager->addParseError( - std::format("Invalid scale passed to monitor {}, failed to find a clean divisor. Suggested nearest scale: {:5f}", pMonitor->szName, searchScale)); + if (!autoScale) { + Debug::log(ERR, "Invalid scale passed to monitor, {} found suggestion {}", pMonitor->scale, searchScale); + g_pConfigManager->addParseError( + std::format("Invalid scale passed to monitor {}, failed to find a clean divisor. Suggested nearest scale: {:5f}", pMonitor->szName, searchScale)); + pMonitor->scale = pMonitor->getDefaultScale(); + } else + pMonitor->scale = searchScale; } - - pMonitor->scale = pMonitor->getDefaultScale(); } } From 7c1ac58a4bfc67addf10a2bd2497e71da923eba3 Mon Sep 17 00:00:00 2001 From: dranull <150595692+dranull@users.noreply.github.com> Date: Mon, 1 Jan 2024 12:02:16 +0000 Subject: [PATCH 464/513] input: Ignore some input events when focus is on a layer surface (#4306) * No motion events with focus on LS on workspace change * Don't check scroll events on decorations with focus on LS --- src/managers/KeybindManager.cpp | 10 ++++++---- src/managers/input/InputManager.cpp | 10 ++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index fc3fcf0d..899003d8 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -880,10 +880,12 @@ void CKeybindManager::changeworkspace(std::string args) { } else pWorkspaceToChangeTo->rememberPrevWorkspace(PCURRENTWORKSPACE); - if (!g_pCompositor->m_pLastFocus) - g_pInputManager->simulateMouseMovement(); - else - g_pInputManager->sendMotionEventsToFocused(); + if (!g_pInputManager->m_bLastFocusOnLS) { + if (g_pCompositor->m_pLastFocus) + g_pInputManager->sendMotionEventsToFocused(); + else + g_pInputManager->simulateMouseMovement(); + } } void CKeybindManager::fullscreenActive(std::string args) { diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 78058a8a..207df738 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -687,11 +687,13 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) { if (!passEvent) return; - const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); - const auto PWINDOW = g_pCompositor->vectorToWindowIdeal(MOUSECOORDS); + if (!m_bLastFocusOnLS) { + const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); + const auto PWINDOW = g_pCompositor->vectorToWindowIdeal(MOUSECOORDS); - if (PWINDOW && PWINDOW->checkInputOnDecos(INPUT_TYPE_AXIS, MOUSECOORDS, e)) - return; + if (PWINDOW && PWINDOW->checkInputOnDecos(INPUT_TYPE_AXIS, MOUSECOORDS, e)) + return; + } wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, factor * e->delta, std::round(factor * e->delta_discrete), e->source); } From 03ebbe18ed8517ee22591eac82cd54322f42cb7d Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 1 Jan 2024 13:03:09 +0100 Subject: [PATCH 465/513] props: bump ver to 0.34.0 --- props.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/props.json b/props.json index 36248fd8..93c30160 100644 --- a/props.json +++ b/props.json @@ -1,3 +1,3 @@ { - "version": "0.33.1" + "version": "0.34.0" } \ No newline at end of file From 33444e1e5ef89efecdf1cf0b3c05daf15e8e29df Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 1 Jan 2024 16:47:54 +0100 Subject: [PATCH 466/513] deps: update wlroots --- src/events/Misc.cpp | 4 ++-- src/render/Renderer.cpp | 4 ++-- subprojects/wlroots | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/events/Misc.cpp b/src/events/Misc.cpp index 91a0ebda..6b77d9c5 100644 --- a/src/events/Misc.cpp +++ b/src/events/Misc.cpp @@ -256,9 +256,9 @@ void Events::listener_newTearingHint(wl_listener* listener, void* data) { const auto PWINDOW = g_pCompositor->getWindowFromSurface(TEARINGHINT->pWlrHint->surface); if (PWINDOW) { - PWINDOW->m_bTearingHint = TEARINGHINT->pWlrHint->hint; + PWINDOW->m_bTearingHint = (bool)TEARINGHINT->pWlrHint->current; - Debug::log(LOG, "Hint {} (window {}) set tearing hint to {}", (uintptr_t)TEARINGHINT->pWlrHint, PWINDOW, (uint32_t)TEARINGHINT->pWlrHint->hint); + Debug::log(LOG, "Hint {} (window {}) set tearing hint to {}", (uintptr_t)TEARINGHINT->pWlrHint, PWINDOW, (uint32_t)TEARINGHINT->pWlrHint->current); } }, NEWCTRL, "TearingController"); diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 88320139..0416d08f 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -161,7 +161,7 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) if (!g_pHyprRenderer->m_bBlockSurfaceFeedback) { wlr_surface_send_frame_done(surface, RDATA->when); - wlr_presentation_surface_textured_on_output(g_pCompositor->m_sWLRPresentation, surface, RDATA->pMonitor->output); + wlr_presentation_surface_textured_on_output(surface, RDATA->pMonitor->output); } g_pHyprOpenGL->blend(true); @@ -905,7 +905,7 @@ bool CHyprRenderer::attemptDirectScanout(CMonitor* pMonitor) { timespec now; clock_gettime(CLOCK_MONOTONIC, &now); wlr_surface_send_frame_done(PSURFACE, &now); - wlr_presentation_surface_scanned_out_on_output(g_pCompositor->m_sWLRPresentation, PSURFACE, pMonitor->output); + wlr_presentation_surface_scanned_out_on_output(PSURFACE, pMonitor->output); if (wlr_output_commit(pMonitor->output)) { if (!m_pLastScanout) { diff --git a/subprojects/wlroots b/subprojects/wlroots index 5d639394..f81c3d93 160000 --- a/subprojects/wlroots +++ b/subprojects/wlroots @@ -1 +1 @@ -Subproject commit 5d639394f3e83b01596dcd166a44a9a1a2583350 +Subproject commit f81c3d93cd6f61b20ae784297679283438def8df From fa5e81230452cb2815f7b4a55d31e33dd4236d60 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 1 Jan 2024 15:48:37 +0000 Subject: [PATCH 467/513] [gha] Nix: update wlroots --- flake.lock | 8 ++++---- flake.nix | 2 +- subprojects/wlroots.wrap | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index f7761728..85a83ff8 100644 --- a/flake.lock +++ b/flake.lock @@ -67,18 +67,18 @@ "flake": false, "locked": { "host": "gitlab.freedesktop.org", - "lastModified": 1701368958, - "narHash": "sha256-7kvyoA91etzVEl9mkA/EJfB6z/PltxX7Xc4gcr7/xlo=", + "lastModified": 1703963193, + "narHash": "sha256-ke8drv6PTrdQDruWbajrRJffP9A9PU6FRyjJGNZRTs4=", "owner": "wlroots", "repo": "wlroots", - "rev": "5d639394f3e83b01596dcd166a44a9a1a2583350", + "rev": "f81c3d93cd6f61b20ae784297679283438def8df", "type": "gitlab" }, "original": { "host": "gitlab.freedesktop.org", "owner": "wlroots", "repo": "wlroots", - "rev": "5d639394f3e83b01596dcd166a44a9a1a2583350", + "rev": "f81c3d93cd6f61b20ae784297679283438def8df", "type": "gitlab" } }, diff --git a/flake.nix b/flake.nix index 6807c0f3..7f9a958b 100644 --- a/flake.nix +++ b/flake.nix @@ -12,7 +12,7 @@ host = "gitlab.freedesktop.org"; owner = "wlroots"; repo = "wlroots"; - rev = "5d639394f3e83b01596dcd166a44a9a1a2583350"; + rev = "f81c3d93cd6f61b20ae784297679283438def8df"; flake = false; }; diff --git a/subprojects/wlroots.wrap b/subprojects/wlroots.wrap index 3624d5aa..915385df 100644 --- a/subprojects/wlroots.wrap +++ b/subprojects/wlroots.wrap @@ -1,7 +1,7 @@ [wrap-git] directory = wlroots url = https://gitlab.freedesktop.org/wlroots/wlroots.git -revision = 5d639394f3e83b01596dcd166a44a9a1a2583350 +revision = f81c3d93cd6f61b20ae784297679283438def8df depth = 1 diff_files = wlroots-meson-build.patch From 069880e37467f5a81c1b549a896f5301ad575aae Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 1 Jan 2024 17:53:00 +0100 Subject: [PATCH 468/513] hyprctl: add systeminfo --- hyprctl/main.cpp | 3 +++ src/debug/HyprCtl.cpp | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/hyprctl/main.cpp b/hyprctl/main.cpp index 7285f5b8..281a74ac 100644 --- a/hyprctl/main.cpp +++ b/hyprctl/main.cpp @@ -51,6 +51,7 @@ commands: setprop splash switchxkblayout + systeminfo version workspacerules workspaces @@ -388,6 +389,8 @@ int main(int argc, char** argv) { request(fullRequest); else if (fullRequest.contains("/kill")) request(fullRequest); + else if (fullRequest.contains("/systeminfo")) + request(fullRequest); else if (fullRequest.contains("/splash")) request(fullRequest); else if (fullRequest.contains("/devices")) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 72d3f6b5..78d20903 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -793,6 +794,39 @@ std::string versionRequest(HyprCtl::eHyprCtlOutputFormat format) { return ""; // make the compiler happy } +std::string systemInfoRequest() { + std::string result = versionRequest(HyprCtl::eHyprCtlOutputFormat::FORMAT_NORMAL); + + result += "\n\nSystem Information:\n"; + + struct utsname unameInfo; + + uname(&unameInfo); + + result += "System name: " + std::string{unameInfo.sysname} + "\n"; + result += "Node name: " + std::string{unameInfo.nodename} + "\n"; + result += "Release: " + std::string{unameInfo.release} + "\n"; + result += "Version: " + std::string{unameInfo.version} + "\n"; + + result += "\n\n"; + +#if defined(__DragonFly__) || defined(__FreeBSD__) + const std::string GPUINFO = execAndGet("pciconf -lv | fgrep -A4 vga"); +#else + const std::string GPUINFO = execAndGet("lspci -vnn | grep VGA"); +#endif + result += "GPU information: \n" + GPUINFO + "\n\n"; + + result += "os-release: " + execAndGet("cat /etc/os-release") + "\n\n"; + + result += "plugins:\n"; + for (auto& pl : g_pPluginSystem->getAllPlugins()) { + result += std::format(" {} by {} ver {}\n", pl->name, pl->author, pl->version); + } + + return result; +} + std::string dispatchRequest(std::string in) { // get rid of the dispatch keyword in = in.substr(in.find_first_of(' ') + 1); @@ -1415,6 +1449,8 @@ std::string getReply(std::string request) { return bindsRequest(format); else if (request == "globalshortcuts") return globalShortcutsRequest(format); + else if (request == "systeminfo") + return systemInfoRequest(); else if (request == "animations") return animationsRequest(format); else if (request == "rollinglog") From 3a189c265d9686c6a922cb4c15d6563cd652e6c7 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 1 Jan 2024 18:03:32 +0100 Subject: [PATCH 469/513] issue templates: make versions spoiler'd --- .github/ISSUE_TEMPLATE/bug.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 90bb9286..b6582979 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -9,12 +9,23 @@ body: --- - - type: input + - type: textarea id: ver attributes: label: Hyprland Version - description: "Paste here the output of `hyprctl version`." - placeholder: Hyprland, built from branch main at commit... + description: "Paste here the output of `hyprctl version`. For hyprland after 0.34.0, paste `hyprctl systeminfo` instead." + value: "
+ System/Version info + + + ```sh + + + + ``` + + +
" validations: required: true From c7ba4606870200e049ff1537f6a1a2882d1099a9 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 1 Jan 2024 18:19:22 +0100 Subject: [PATCH 470/513] wlroots: update version patches --- CMakeLists.txt | 2 +- subprojects/packagefiles/wlroots-meson-build.patch | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bedb7bbf..0dbcea09 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,7 +57,7 @@ ExternalProject_Add( wlroots PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots - PATCH_COMMAND sed -E -i -e "s/(soversion = 13)([^032]|$$)/soversion = 13032/g" meson.build + PATCH_COMMAND sed -E -i -e "s/(soversion = version_minor.to_int() - 5)([^032]|$$)/soversion = 13032/g" meson.build CONFIGURE_COMMAND meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $,-Db_sanitize=address,-Db_sanitize=none> && meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $,-Db_sanitize=address,-Db_sanitize=none> --reconfigure BUILD_COMMAND ninja -C build BUILD_ALWAYS true diff --git a/subprojects/packagefiles/wlroots-meson-build.patch b/subprojects/packagefiles/wlroots-meson-build.patch index fd6f84db..4e911980 100644 --- a/subprojects/packagefiles/wlroots-meson-build.patch +++ b/subprojects/packagefiles/wlroots-meson-build.patch @@ -38,7 +38,7 @@ index 29b103a..0b6e5a4 100644 # necessary for bugfix releases. Increasing soversion is required because # wlroots never guarantees ABI stability -- only API stability is guaranteed # between minor releases. --soversion = 13 +-soversion = version_minor.to_int() - 5 +soversion = 13032 little_endian = target_machine.endian() == 'little' From 4e0e8d933e8eec460a31e3a811f6f1a2717a1ec1 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Mon, 1 Jan 2024 18:26:48 +0100 Subject: [PATCH 471/513] CI: add stalebot --- .github/workflows/stale.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/stale.yml diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000..09f7a992 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,25 @@ +# This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time. +# +# You can adjust the behavior by modifying this file. +# For more information, see: +# https://github.com/actions/stale +name: Mark stale issues and pull requests + +on: + schedule: + - cron: '26 0 * * *' + +jobs: + stale: + + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + + steps: + - uses: actions/stale@v5 + with: + repo-token: ${{ secrets.STALEBOT_PAT }} + stale-issue-label: 'stale' + stale-pr-label: 'stale' From 0be36cd02d20617010ac3efff198fe7df0d6d07a Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 1 Jan 2024 18:29:03 +0100 Subject: [PATCH 472/513] cmakelists: fix wlroots patch sed --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0dbcea09..88e094a7 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,7 +57,7 @@ ExternalProject_Add( wlroots PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots - PATCH_COMMAND sed -E -i -e "s/(soversion = version_minor.to_int() - 5)([^032]|$$)/soversion = 13032/g" meson.build + PATCH_COMMAND sed -E -i -e "s/(soversion = .*$)/soversion = 13032/g" meson.build CONFIGURE_COMMAND meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $,-Db_sanitize=address,-Db_sanitize=none> && meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $,-Db_sanitize=address,-Db_sanitize=none> --reconfigure BUILD_COMMAND ninja -C build BUILD_ALWAYS true From 37b76cd1caed209e20e0e353671abf6ba4346b42 Mon Sep 17 00:00:00 2001 From: rszyma Date: Mon, 1 Jan 2024 18:29:51 +0100 Subject: [PATCH 473/513] keybinds: fix keys getting stuck + minor refactor & optimizations to keybind handling (#4304) --- src/config/ConfigManager.cpp | 2 +- src/managers/KeybindManager.cpp | 160 ++++++++++++++++++++++---------- src/managers/KeybindManager.hpp | 53 ++++++----- 3 files changed, 142 insertions(+), 73 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index ee198ded..28959128 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -935,7 +935,7 @@ void CConfigManager::handleBind(const std::string& command, const std::string& v g_pKeybindManager->addKeybind( SKeybind{"", std::stoi(KEY.substr(5)), MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent, ignoreMods}); else - g_pKeybindManager->addKeybind(SKeybind{KEY, -1, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent, ignoreMods}); + g_pKeybindManager->addKeybind(SKeybind{KEY, 0, MOD, HANDLER, COMMAND, locked, m_szCurrentSubmap, release, repeat, mouse, nonConsuming, transparent, ignoreMods}); } } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 899003d8..d379a408 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -7,6 +7,7 @@ #include #include +#include #if defined(__linux__) #include #elif defined(__NetBSD__) || defined(__OpenBSD__) @@ -95,7 +96,7 @@ void CKeybindManager::addKeybind(SKeybind kb) { void CKeybindManager::removeKeybind(uint32_t mod, const std::string& key) { for (auto it = m_lKeybinds.begin(); it != m_lKeybinds.end(); ++it) { if (isNumber(key) && std::stoi(key) > 9) { - const auto KEYNUM = std::stoi(key); + const uint32_t KEYNUM = std::stoi(key); if (it->modmask == mod && it->keycode == KEYNUM) { it = m_lKeybinds.erase(it); @@ -137,6 +138,22 @@ uint32_t CKeybindManager::stringToModMask(std::string mods) { return modMask; } +uint32_t CKeybindManager::keycodeToModifier(xkb_keycode_t keycode) { + switch (keycode - 8) { + case KEY_LEFTMETA: return WLR_MODIFIER_LOGO; + case KEY_RIGHTMETA: return WLR_MODIFIER_LOGO; + case KEY_LEFTSHIFT: return WLR_MODIFIER_SHIFT; + case KEY_RIGHTSHIFT: return WLR_MODIFIER_SHIFT; + case KEY_LEFTCTRL: return WLR_MODIFIER_CTRL; + case KEY_RIGHTCTRL: return WLR_MODIFIER_CTRL; + case KEY_LEFTALT: return WLR_MODIFIER_ALT; + case KEY_RIGHTALT: return WLR_MODIFIER_ALT; + case KEY_CAPSLOCK: return WLR_MODIFIER_CAPS; + case KEY_NUMLOCK: return WLR_MODIFIER_MOD2; + default: return 0; + } +} + void CKeybindManager::updateXKBTranslationState() { if (m_pXKBTranslationState) { xkb_keymap_unref(xkb_state_get_keymap(m_pXKBTranslationState)); @@ -261,8 +278,7 @@ void CKeybindManager::switchToWindow(CWindow* PWINDOWTOCHANGETO) { bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard) { if (!g_pCompositor->m_bSessionActive || g_pCompositor->m_bUnsafeState) { - m_dPressedKeycodes.clear(); - m_dPressedKeysyms.clear(); + m_dPressedKeys.clear(); return true; } @@ -291,7 +307,13 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard m_uLastCode = KEYCODE; m_uLastMouseCode = 0; - bool mouseBindWasActive = ensureMouseBindState(); + bool mouseBindWasActive = ensureMouseBindState(); + + const auto KEY = SPressedKeyWithMods{ + .keysym = keysym, + .keycode = KEYCODE, + .modmaskAtPressTime = MODS, + }; bool found = false; if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) { @@ -302,16 +324,13 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard m_pActiveKeybind = nullptr; } - m_dPressedKeycodes.push_back(KEYCODE); - m_dPressedKeysyms.push_back(keysym); + m_dPressedKeys.push_back(KEY); - found = handleKeybinds(MODS, "", keysym, 0, true, e->time_msec) || found; - - found = handleKeybinds(MODS, "", 0, KEYCODE, true, e->time_msec) || found; + found = handleKeybinds(MODS, KEY, true); if (found) shadowKeybinds(keysym, KEYCODE); - } else if (e->state == WL_KEYBOARD_KEY_STATE_RELEASED) { + } else { // key release // clean repeat if (m_pActiveKeybindEventSource) { wl_event_source_remove(m_pActiveKeybindEventSource); @@ -319,12 +338,23 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard m_pActiveKeybind = nullptr; } - m_dPressedKeycodes.erase(std::remove(m_dPressedKeycodes.begin(), m_dPressedKeycodes.end(), KEYCODE), m_dPressedKeycodes.end()); - m_dPressedKeysyms.erase(std::remove(m_dPressedKeysyms.begin(), m_dPressedKeysyms.end(), keysym), m_dPressedKeysyms.end()); - - found = handleKeybinds(MODS, "", keysym, 0, false, e->time_msec) || found; - - found = handleKeybinds(MODS, "", 0, KEYCODE, false, e->time_msec) || found; + bool foundInPressedKeys = false; + for (auto it = m_dPressedKeys.begin(); it != m_dPressedKeys.end();) { + if (it->keycode == KEYCODE) { + if (!foundInPressedKeys) { + found = handleKeybinds(MODS, *it, false); + foundInPressedKeys = true; + } + it = m_dPressedKeys.erase(it); + } else { + ++it; + } + } + if (!foundInPressedKeys) { + Debug::log(ERR, "BUG THIS: key not found in m_dPressedKeys"); + // fallback with wrong `KEY.modmaskAtPressTime`, this can be buggy + found = handleKeybinds(MODS, KEY, false); + } shadowKeybinds(); } @@ -347,14 +377,14 @@ bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) { bool found = false; if (e->source == WLR_AXIS_SOURCE_WHEEL && e->orientation == WLR_AXIS_ORIENTATION_VERTICAL) { if (e->delta < 0) - found = handleKeybinds(MODS, "mouse_down", 0, 0, true, 0); + found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_down"}, true); else - found = handleKeybinds(MODS, "mouse_up", 0, 0, true, 0); + found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_up"}, true); } else if (e->source == WLR_AXIS_SOURCE_WHEEL && e->orientation == WLR_AXIS_ORIENTATION_HORIZONTAL) { if (e->delta < 0) - found = handleKeybinds(MODS, "mouse_left", 0, 0, true, 0); + found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_left"}, true); else - found = handleKeybinds(MODS, "mouse_right", 0, 0, true, 0); + found = handleKeybinds(MODS, SPressedKeyWithMods{.keyName = "mouse_right"}, true); } if (found) @@ -372,15 +402,40 @@ bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) { m_uLastCode = 0; m_uTimeLastMs = e->time_msec; - bool mouseBindWasActive = ensureMouseBindState(); + bool mouseBindWasActive = ensureMouseBindState(); + + const auto KEY_NAME = "mouse:" + std::to_string(e->button); + + const auto KEY = SPressedKeyWithMods{ + .keyName = KEY_NAME, + .modmaskAtPressTime = MODS, + }; if (e->state == WLR_BUTTON_PRESSED) { - found = handleKeybinds(MODS, "mouse:" + std::to_string(e->button), 0, 0, true, 0); + m_dPressedKeys.push_back(KEY); + + found = handleKeybinds(MODS, KEY, true); if (found) shadowKeybinds(); } else { - found = handleKeybinds(MODS, "mouse:" + std::to_string(e->button), 0, 0, false, 0); + bool foundInPressedKeys = false; + for (auto it = m_dPressedKeys.begin(); it != m_dPressedKeys.end();) { + if (it->keyName == KEY_NAME) { + if (!foundInPressedKeys) { + found = handleKeybinds(MODS, *it, false); + foundInPressedKeys = true; + } + it = m_dPressedKeys.erase(it); + } else { + ++it; + } + } + if (!foundInPressedKeys) { + Debug::log(ERR, "BUG THIS: key not found in m_dPressedKeys (2)"); + // fallback with wrong `KEY.modmaskAtPressTime`, this can be buggy + found = handleKeybinds(MODS, KEY, false); + } shadowKeybinds(); } @@ -397,15 +452,15 @@ void CKeybindManager::resizeWithBorder(wlr_pointer_button_event* e) { } void CKeybindManager::onSwitchEvent(const std::string& switchName) { - handleKeybinds(0, "switch:" + switchName, 0, 0, true, 0); + handleKeybinds(0, SPressedKeyWithMods{.keyName = "switch:" + switchName}, true); } void CKeybindManager::onSwitchOnEvent(const std::string& switchName) { - handleKeybinds(0, "switch:on:" + switchName, 0, 0, true, 0); + handleKeybinds(0, SPressedKeyWithMods{.keyName = "switch:on:" + switchName}, true); } void CKeybindManager::onSwitchOffEvent(const std::string& switchName) { - handleKeybinds(0, "switch:off:" + switchName, 0, 0, true, 0); + handleKeybinds(0, SPressedKeyWithMods{.keyName = "switch:off:" + switchName}, true); } int repeatKeyHandler(void* data) { @@ -424,7 +479,7 @@ int repeatKeyHandler(void* data) { return 0; } -bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string& key, const xkb_keysym_t& keysym, const int& keycode, bool pressed, uint32_t time) { +bool CKeybindManager::handleKeybinds(const uint32_t modmask, const SPressedKeyWithMods& key, bool pressed) { bool found = false; if (g_pCompositor->m_sSeat.exclusiveClient) @@ -441,22 +496,19 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string& ((modmask != k.modmask && !k.ignoreMods) || (g_pCompositor->m_sSeat.exclusiveClient && !k.locked) || k.submap != m_szCurrentSelectedSubmap || k.shadowed)) continue; - if (!key.empty()) { - if (key != k.key) + if (!key.keyName.empty()) { + if (key.keyName != k.key) continue; - } else if (k.keycode != -1) { - if (keycode != k.keycode) + } else if (k.keycode != 0) { + if (key.keycode != k.keycode) continue; } else { - if (keysym == 0) - continue; // this is a keycode check run - // oMg such performance hit!!11! // this little maneouver is gonna cost us 4µs const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE); const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY); - if (keysym != KBKEY && keysym != KBKEYUPPER) + if (key.keysym != KBKEY && key.keysym != KBKEYUPPER) continue; } @@ -468,12 +520,24 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string& continue; } - if (!pressed && !k.release && !SPECIALDISPATCHER) { - if (k.nonConsuming) - continue; + if (!pressed) { + // Require mods to be matching when the key was first pressed. + if (key.modmaskAtPressTime != modmask) { + // Handle properly `bindr` where a key is itself a bind mod for example: + // "bindr = SUPER, SUPER_L, exec, $launcher". + // This needs to be handled separately for the above case, because `key.modmaskAtPressTime` is set + // from currently pressed keys as programs see them, but it doesn't yet include the currently + // pressed mod key, which is still being handled internally. + if (keycodeToModifier(key.keycode) == key.modmaskAtPressTime) + continue; - found = true; // suppress the event - continue; + } else if (!k.release && !SPECIALDISPATCHER) { + if (k.nonConsuming) + continue; + + found = true; // suppress the event + continue; + } } const auto DISPATCHER = m_mDispatchers.find(k.mouse ? "mouse" : k.handler); @@ -488,7 +552,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string& Debug::log(ERR, "Invalid handler in a keybind! (handler {} does not exist)", k.handler); } else { // call the dispatcher - Debug::log(LOG, "Keybind triggered, calling dispatcher ({}, {}, {})", modmask, key, keysym); + Debug::log(LOG, "Keybind triggered, calling dispatcher ({}, {}, {})", modmask, key.keyName, key.keysym); m_iPassPressed = (int)pressed; @@ -521,7 +585,7 @@ bool CKeybindManager::handleKeybinds(const uint32_t& modmask, const std::string& return found; } -void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const int& doesntHaveCode) { +void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const uint32_t doesntHaveCode) { // shadow disables keybinds after one has been triggered for (auto& k : m_lKeybinds) { @@ -534,22 +598,20 @@ void CKeybindManager::shadowKeybinds(const xkb_keysym_t& doesntHave, const int& const auto KBKEY = xkb_keysym_from_name(k.key.c_str(), XKB_KEYSYM_CASE_INSENSITIVE); const auto KBKEYUPPER = xkb_keysym_to_upper(KBKEY); - for (auto& pk : m_dPressedKeysyms) { - if ((pk == KBKEY || pk == KBKEYUPPER)) { + for (auto& pk : m_dPressedKeys) { + if ((pk.keysym != 0 && (pk.keysym == KBKEY || pk.keysym == KBKEYUPPER))) { shadow = true; - if (pk == doesntHave && doesntHave != 0) { + if (pk.keysym == doesntHave && doesntHave != 0) { shadow = false; break; } } - } - for (auto& pk : m_dPressedKeycodes) { - if (pk == k.keycode) { + if (pk.keycode != 0 && pk.keycode == k.keycode) { shadow = true; - if (pk == doesntHaveCode && doesntHaveCode != 0 && doesntHaveCode != -1) { + if (pk.keycode == doesntHaveCode && doesntHaveCode != 0) { shadow = false; break; } diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 73997dd6..631b0147 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -12,7 +12,7 @@ class CPluginSystem; struct SKeybind { std::string key = ""; - int keycode = -1; + uint32_t keycode = 0; uint32_t modmask = 0; std::string handler = ""; std::string arg = ""; @@ -36,6 +36,13 @@ enum eFocusWindowMode { MODE_PID }; +struct SPressedKeyWithMods { + std::string keyName = ""; + xkb_keysym_t keysym = 0; + uint32_t keycode = 0; + uint32_t modmaskAtPressTime = 0; +}; + class CKeybindManager { public: CKeybindManager(); @@ -51,8 +58,9 @@ class CKeybindManager { void addKeybind(SKeybind); void removeKeybind(uint32_t, const std::string&); uint32_t stringToModMask(std::string); + uint32_t keycodeToModifier(xkb_keycode_t); void clearKeybinds(); - void shadowKeybinds(const xkb_keysym_t& doesntHave = 0, const int& doesntHaveCode = 0); + void shadowKeybinds(const xkb_keysym_t& doesntHave = 0, const uint32_t doesntHaveCode = 0); std::unordered_map> m_mDispatchers; @@ -63,38 +71,37 @@ class CKeybindManager { std::list m_lKeybinds; private: - std::deque m_dPressedKeysyms; - std::deque m_dPressedKeycodes; + std::deque m_dPressedKeys; - inline static std::string m_szCurrentSelectedSubmap = ""; + inline static std::string m_szCurrentSelectedSubmap = ""; - SKeybind* m_pActiveKeybind = nullptr; + SKeybind* m_pActiveKeybind = nullptr; - uint32_t m_uTimeLastMs = 0; - uint32_t m_uLastCode = 0; - uint32_t m_uLastMouseCode = 0; + uint32_t m_uTimeLastMs = 0; + uint32_t m_uLastCode = 0; + uint32_t m_uLastMouseCode = 0; - bool m_bIsMouseBindActive = false; - std::vector m_vPressedSpecialBinds; + bool m_bIsMouseBindActive = false; + std::vector m_vPressedSpecialBinds; - int m_iPassPressed = -1; // used for pass + int m_iPassPressed = -1; // used for pass - CTimer m_tScrollTimer; + CTimer m_tScrollTimer; - bool handleKeybinds(const uint32_t&, const std::string&, const xkb_keysym_t&, const int&, bool, uint32_t); + bool handleKeybinds(const uint32_t, const SPressedKeyWithMods&, bool); - bool handleInternalKeybinds(xkb_keysym_t); - bool handleVT(xkb_keysym_t); + bool handleInternalKeybinds(xkb_keysym_t); + bool handleVT(xkb_keysym_t); - xkb_state* m_pXKBTranslationState = nullptr; + xkb_state* m_pXKBTranslationState = nullptr; - void updateXKBTranslationState(); - bool ensureMouseBindState(); + void updateXKBTranslationState(); + bool ensureMouseBindState(); - static bool tryMoveFocusToMonitor(CMonitor* monitor); - static void moveWindowOutOfGroup(CWindow* pWindow, const std::string& dir = ""); - static void moveWindowIntoGroup(CWindow* pWindow, CWindow* pWindowInDirection); - static void switchToWindow(CWindow* PWINDOWTOCHANGETO); + static bool tryMoveFocusToMonitor(CMonitor* monitor); + static void moveWindowOutOfGroup(CWindow* pWindow, const std::string& dir = ""); + static void moveWindowIntoGroup(CWindow* pWindow, CWindow* pWindowInDirection); + static void switchToWindow(CWindow* PWINDOWTOCHANGETO); // -------------- Dispatchers -------------- // static void killActive(std::string); From d4e68ab60216596867d6ee08b1e96ff0eeaec80e Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Mon, 1 Jan 2024 18:34:15 +0100 Subject: [PATCH 474/513] CI: allow manual stale execution --- .github/workflows/stale.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 09f7a992..223186b5 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -8,6 +8,7 @@ name: Mark stale issues and pull requests on: schedule: - cron: '26 0 * * *' + workflow_dispatch: jobs: stale: From 46753b1f22478c64222e5d9f7e0fb4c10b001be6 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 1 Jan 2024 18:37:49 +0100 Subject: [PATCH 475/513] CI: limit stalebot ops per run --- .github/workflows/stale.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 223186b5..8955517f 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -7,7 +7,7 @@ name: Mark stale issues and pull requests on: schedule: - - cron: '26 0 * * *' + - cron: '7 */4 * * *' workflow_dispatch: jobs: @@ -24,3 +24,4 @@ jobs: repo-token: ${{ secrets.STALEBOT_PAT }} stale-issue-label: 'stale' stale-pr-label: 'stale' + operations-per-run: 40 From 42ab06e7c84fed39b3f853f213ef2966f23baaa5 Mon Sep 17 00:00:00 2001 From: bvr-yr <130279855+bvr-yr@users.noreply.github.com> Date: Mon, 1 Jan 2024 21:58:01 +0300 Subject: [PATCH 476/513] meson: fix wlroots patch (#4324) --- subprojects/packagefiles/wlroots-meson-build.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/packagefiles/wlroots-meson-build.patch b/subprojects/packagefiles/wlroots-meson-build.patch index 4e911980..a184eb77 100644 --- a/subprojects/packagefiles/wlroots-meson-build.patch +++ b/subprojects/packagefiles/wlroots-meson-build.patch @@ -35,9 +35,9 @@ index 29b103a..0b6e5a4 100644 --- a/meson.build +++ b/meson.build @@ -15,7 +15,7 @@ project( - # necessary for bugfix releases. Increasing soversion is required because - # wlroots never guarantees ABI stability -- only API stability is guaranteed - # between minor releases. + version_major = version.split('.')[0] + version_minor = version.split('.')[1] + assert(version_major == '0') -soversion = version_minor.to_int() - 5 +soversion = 13032 From 1a4f23eb2fee77b23b2cc6ff1fbfc87f60f10314 Mon Sep 17 00:00:00 2001 From: q234rty Date: Tue, 2 Jan 2024 03:20:27 +0800 Subject: [PATCH 477/513] renderer: Only force nearest neighbor when the sizes are off by one or two (#4325) Fixes rendering issues in arch's extra/telegram-desktop --- src/render/Renderer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 0416d08f..533215ce 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -118,6 +118,7 @@ static void renderSurface(struct wlr_surface* surface, int x, int y, void* data) const auto NEARESTNEIGHBORSET = g_pHyprOpenGL->m_RenderData.useNearestNeighbor; if (std::floor(RDATA->pMonitor->scale) != RDATA->pMonitor->scale /* Fractional */ && surface->current.scale == 1 /* fs protocol */ && windowBox.size() != Vector2D{surface->current.buffer_width, surface->current.buffer_height} /* misaligned */ && + DELTALESSTHAN(windowBox.width, surface->current.buffer_width, 3) && DELTALESSTHAN(windowBox.height, surface->current.buffer_height, 3) /* off by one-or-two */ && (!RDATA->pWindow || (!RDATA->pWindow->m_vRealSize.isBeingAnimated() && !INTERACTIVERESIZEINPROGRESS)) /* not window or not animated/resizing */) g_pHyprOpenGL->m_RenderData.useNearestNeighbor = true; From 1607e967041fd3311411de0def8cdc0610274f98 Mon Sep 17 00:00:00 2001 From: Zach DeCook Date: Mon, 1 Jan 2024 17:05:26 -0500 Subject: [PATCH 478/513] HookSystem: rename PAGESIZE_VAR from PAGESIZE to avoid conflict (#4321) --- src/plugins/HookSystem.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/HookSystem.cpp b/src/plugins/HookSystem.cpp index e52fd749..a7625ffe 100644 --- a/src/plugins/HookSystem.cpp +++ b/src/plugins/HookSystem.cpp @@ -190,9 +190,9 @@ bool CFunctionHook::hook() { (uint64_t)((uint8_t*)m_pSource + sizeof(ABSOLUTE_JMP_ADDRESS)); // make jump to hk - const auto PAGESIZE = sysconf(_SC_PAGE_SIZE); - const uint8_t* PROTSTART = (uint8_t*)m_pSource - ((uint64_t)m_pSource % PAGESIZE); - const size_t PROTLEN = std::ceil((float)(ORIGSIZE + ((uint64_t)m_pSource - (uint64_t)PROTSTART)) / (float)PAGESIZE) * PAGESIZE; + const auto PAGESIZE_VAR = sysconf(_SC_PAGE_SIZE); + const uint8_t* PROTSTART = (uint8_t*)m_pSource - ((uint64_t)m_pSource % PAGESIZE_VAR); + const size_t PROTLEN = std::ceil((float)(ORIGSIZE + ((uint64_t)m_pSource - (uint64_t)PROTSTART)) / (float)PAGESIZE_VAR) * PAGESIZE_VAR; mprotect((uint8_t*)PROTSTART, PROTLEN, PROT_READ | PROT_WRITE | PROT_EXEC); memcpy((uint8_t*)m_pSource, ABSOLUTE_JMP_ADDRESS, sizeof(ABSOLUTE_JMP_ADDRESS)); From 583b05a8c67772e96e534e37e21b608fb5723546 Mon Sep 17 00:00:00 2001 From: dranull <150595692+dranull@users.noreply.github.com> Date: Tue, 2 Jan 2024 12:37:03 +0000 Subject: [PATCH 479/513] groupbar: Drag single window instead of destroying group (#4327) --- src/render/decorations/CHyprGroupBarDecoration.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 33ecff6a..61409256 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -317,6 +317,9 @@ void refreshGroupBarGradients() { } bool CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) { + if (m_pWindow == m_pWindow->m_sGroupData.pNextWindow) + return false; + const float BARRELATIVEX = pos.x - assignedBoxGlobal().x; const int WINDOWINDEX = (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); From 813af393f1b61ecd0105e126681986e58e73ffee Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 2 Jan 2024 14:21:22 +0100 Subject: [PATCH 480/513] layout: update rules before applying fullscreen nodes in layouts --- src/Compositor.cpp | 1 - src/layout/DwindleLayout.cpp | 5 ++++- src/layout/MasterLayout.cpp | 3 +++ src/render/decorations/CHyprBorderDecoration.cpp | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 26bd56c4..af03e025 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2284,7 +2284,6 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode g_pXWaylandManager->setWindowFullscreen(pWindow, pWindow->shouldSendFullscreenState()); - pWindow->updateDynamicRules(); updateWindowAnimatedDecorationValues(pWindow); // make all windows on the same workspace under the fullscreen window diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 53ddb86e..76b9aeb4 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -780,6 +780,9 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree pWindow->m_bIsFullscreen = on; PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow; + pWindow->updateDynamicRules(); + pWindow->updateWindowDecos(); + g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)}); EMIT_HOOK_EVENT("fullscreen", pWindow); @@ -824,7 +827,7 @@ void CHyprDwindleLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscree pWindow->m_vPosition = fakeNode.box.pos(); pWindow->m_vSize = fakeNode.box.size(); - applyNodeDataToWindow(&fakeNode); + applyNodeDataToWindow(&fakeNode, true); } } diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 65f85691..63389c3a 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -883,6 +883,9 @@ void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreen pWindow->m_bIsFullscreen = on; PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow; + pWindow->updateDynamicRules(); + pWindow->updateWindowDecos(); + g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)}); EMIT_HOOK_EVENT("fullscreen", pWindow); diff --git a/src/render/decorations/CHyprBorderDecoration.cpp b/src/render/decorations/CHyprBorderDecoration.cpp index 4e3e824e..77ebdd57 100644 --- a/src/render/decorations/CHyprBorderDecoration.cpp +++ b/src/render/decorations/CHyprBorderDecoration.cpp @@ -104,5 +104,5 @@ std::string CHyprBorderDecoration::getDisplayName() { } bool CHyprBorderDecoration::doesntWantBorders() { - return !m_pWindow->m_sSpecialRenderData.border || m_pWindow->m_bX11DoesntWantBorders; + return !m_pWindow->m_sSpecialRenderData.border || m_pWindow->m_bX11DoesntWantBorders || m_pWindow->getRealBorderSize() == 0; } From bd3ea8dcb5f7803b0cc05e25f84200102c0fad21 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 2 Jan 2024 14:25:18 +0100 Subject: [PATCH 481/513] examples: remove example plugin closes #4329 --- example/examplePlugin/Makefile | 8 -- example/examplePlugin/customDecoration.cpp | 74 ---------------- example/examplePlugin/customDecoration.hpp | 29 ------- example/examplePlugin/customLayout.cpp | 80 ----------------- example/examplePlugin/customLayout.hpp | 32 ------- example/examplePlugin/globals.hpp | 5 -- example/examplePlugin/main.cpp | 99 ---------------------- 7 files changed, 327 deletions(-) delete mode 100644 example/examplePlugin/Makefile delete mode 100644 example/examplePlugin/customDecoration.cpp delete mode 100644 example/examplePlugin/customDecoration.hpp delete mode 100644 example/examplePlugin/customLayout.cpp delete mode 100644 example/examplePlugin/customLayout.hpp delete mode 100644 example/examplePlugin/globals.hpp delete mode 100644 example/examplePlugin/main.cpp diff --git a/example/examplePlugin/Makefile b/example/examplePlugin/Makefile deleted file mode 100644 index bb79532a..00000000 --- a/example/examplePlugin/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# compile with HYPRLAND_HEADERS= make all -# make sure that the path above is to the root hl repo directory, NOT src/ -# and that you have ran `make protocols` in the hl dir. - -all: - $(CXX) -shared -fPIC --no-gnu-unique main.cpp customLayout.cpp customDecoration.cpp -o examplePlugin.so -g `pkg-config --cflags pixman-1 libdrm hyprland` -std=c++2b -clean: - rm ./examplePlugin.so diff --git a/example/examplePlugin/customDecoration.cpp b/example/examplePlugin/customDecoration.cpp deleted file mode 100644 index e2b5d136..00000000 --- a/example/examplePlugin/customDecoration.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "customDecoration.hpp" -#include -#include -#include "globals.hpp" - -CCustomDecoration::CCustomDecoration(CWindow* pWindow) { - m_pWindow = pWindow; - m_vLastWindowPos = pWindow->m_vRealPosition.vec(); - m_vLastWindowSize = pWindow->m_vRealSize.vec(); -} - -CCustomDecoration::~CCustomDecoration() { - damageEntire(); -} - -SWindowDecorationExtents CCustomDecoration::getWindowDecorationExtents() { - return m_seExtents; -} - -void CCustomDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& offset) { - if (!g_pCompositor->windowValidMapped(m_pWindow)) - return; - - if (!m_pWindow->m_sSpecialRenderData.decorate) - return; - - static auto* const PCOLOR = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:example:border_color")->intValue; - static auto* const PROUNDING = &HyprlandAPI::getConfigValue(PHANDLE, "decoration:rounding")->intValue; - static auto* const PBORDERSIZE = &HyprlandAPI::getConfigValue(PHANDLE, "general:border_size")->intValue; - - const auto ROUNDING = !m_pWindow->m_sSpecialRenderData.rounding ? - 0 : - (m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying() == -1 ? *PROUNDING : m_pWindow->m_sAdditionalConfigData.rounding.toUnderlying()); - - // draw the border - CBox fullBox = {(int)(m_vLastWindowPos.x - *PBORDERSIZE), (int)(m_vLastWindowPos.y - *PBORDERSIZE), (int)(m_vLastWindowSize.x + 2.0 * *PBORDERSIZE), - (int)(m_vLastWindowSize.y + 2.0 * *PBORDERSIZE)}; - - fullBox.x -= pMonitor->vecPosition.x; - fullBox.y -= pMonitor->vecPosition.y; - - m_seExtents = {{m_vLastWindowPos.x - fullBox.x - pMonitor->vecPosition.x + 2, m_vLastWindowPos.y - fullBox.y - pMonitor->vecPosition.y + 2}, - {fullBox.x + fullBox.width + pMonitor->vecPosition.x - m_vLastWindowPos.x - m_vLastWindowSize.x + 2, - fullBox.y + fullBox.height + pMonitor->vecPosition.y - m_vLastWindowPos.y - m_vLastWindowSize.y + 2}}; - - fullBox.x += offset.x; - fullBox.y += offset.y; - - if (fullBox.width < 1 || fullBox.height < 1) - return; // don't draw invisible shadows - - g_pHyprOpenGL->scissor((CBox*)nullptr); - - fullBox.scale(pMonitor->scale); - g_pHyprOpenGL->renderBorder(&fullBox, CColor(*PCOLOR), *PROUNDING * pMonitor->scale + *PBORDERSIZE * 2, a); -} - -eDecorationType CCustomDecoration::getDecorationType() { - return DECORATION_CUSTOM; -} - -void CCustomDecoration::updateWindow(CWindow* pWindow) { - - m_vLastWindowPos = pWindow->m_vRealPosition.vec(); - m_vLastWindowSize = pWindow->m_vRealSize.vec(); - - damageEntire(); -} - -void CCustomDecoration::damageEntire() { - CBox dm = {(int)(m_vLastWindowPos.x - m_seExtents.topLeft.x), (int)(m_vLastWindowPos.y - m_seExtents.topLeft.y), - (int)(m_vLastWindowSize.x + m_seExtents.topLeft.x + m_seExtents.bottomRight.x), (int)m_seExtents.topLeft.y}; - g_pHyprRenderer->damageBox(&dm); -} \ No newline at end of file diff --git a/example/examplePlugin/customDecoration.hpp b/example/examplePlugin/customDecoration.hpp deleted file mode 100644 index dbb0c0e2..00000000 --- a/example/examplePlugin/customDecoration.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#define WLR_USE_UNSTABLE - -#include - -class CCustomDecoration : public IHyprWindowDecoration { - public: - CCustomDecoration(CWindow*); - virtual ~CCustomDecoration(); - - virtual SWindowDecorationExtents getWindowDecorationExtents(); - - virtual void draw(CMonitor*, float a, const Vector2D& offset); - - virtual eDecorationType getDecorationType(); - - virtual void updateWindow(CWindow*); - - virtual void damageEntire(); - - private: - SWindowDecorationExtents m_seExtents; - - CWindow* m_pWindow = nullptr; - - Vector2D m_vLastWindowPos; - Vector2D m_vLastWindowSize; -}; \ No newline at end of file diff --git a/example/examplePlugin/customLayout.cpp b/example/examplePlugin/customLayout.cpp deleted file mode 100644 index 8001c72d..00000000 --- a/example/examplePlugin/customLayout.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include "customLayout.hpp" -#include -#include "globals.hpp" - -void CHyprCustomLayout::onWindowCreatedTiling(CWindow* pWindow) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); - const auto SIZE = PMONITOR->vecSize; - - // these are used for focus and move calculations, and are *required* to touch for moving focus to work properly. - pWindow->m_vPosition = Vector2D{(SIZE.x / 2.0) * (m_vWindowData.size() % 2), (SIZE.y / 2.0) * (int)(m_vWindowData.size() > 1)}; - pWindow->m_vSize = SIZE / 2.0; - - // this is the actual pos and size of the window (where it's rendered) - pWindow->m_vRealPosition = pWindow->m_vPosition + Vector2D{10, 10}; - pWindow->m_vRealSize = pWindow->m_vSize - Vector2D{20, 20}; - - const auto PDATA = &m_vWindowData.emplace_back(); - PDATA->pWindow = pWindow; -} - -void CHyprCustomLayout::onWindowRemovedTiling(CWindow* pWindow) { - std::erase_if(m_vWindowData, [&](const auto& other) { return other.pWindow == pWindow; }); -} - -bool CHyprCustomLayout::isWindowTiled(CWindow* pWindow) { - return std::find_if(m_vWindowData.begin(), m_vWindowData.end(), [&](const auto& other) { return other.pWindow == pWindow; }) != m_vWindowData.end(); -} - -void CHyprCustomLayout::recalculateMonitor(const int& eIdleInhibitMode) { - ; // empty -} - -void CHyprCustomLayout::recalculateWindow(CWindow* pWindow) { - ; // empty -} - -void CHyprCustomLayout::resizeActiveWindow(const Vector2D& delta, CWindow* pWindow) { - ; // empty -} - -void CHyprCustomLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode mode, bool on) { - ; // empty -} - -std::any CHyprCustomLayout::layoutMessage(SLayoutMessageHeader header, std::string content) { - return ""; -} - -SWindowRenderLayoutHints CHyprCustomLayout::requestRenderHints(CWindow* pWindow) { - return {}; -} - -void CHyprCustomLayout::switchWindows(CWindow* pWindowA, CWindow* pWindowB) { - ; // empty -} - -void CHyprCustomLayout::alterSplitRatio(CWindow* pWindow, float delta, bool exact) { - ; // empty -} - -std::string CHyprCustomLayout::getLayoutName() { - return "custom"; -} - -void CHyprCustomLayout::replaceWindowDataWith(CWindow* from, CWindow* to) { - ; // empty -} - -void CHyprCustomLayout::onEnable() { - for (auto& w : g_pCompositor->m_vWindows) { - if (w->isHidden() || !w->m_bIsMapped || w->m_bFadingOut || w->m_bIsFloating) - continue; - - onWindowCreatedTiling(w.get()); - } -} - -void CHyprCustomLayout::onDisable() { - m_vWindowData.clear(); -} \ No newline at end of file diff --git a/example/examplePlugin/customLayout.hpp b/example/examplePlugin/customLayout.hpp deleted file mode 100644 index 44797ccc..00000000 --- a/example/examplePlugin/customLayout.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#define WLR_USE_UNSTABLE - -#include - -struct SWindowData { - CWindow* pWindow = nullptr; -}; - -class CHyprCustomLayout : public IHyprLayout { - public: - virtual void onWindowCreatedTiling(CWindow*); - virtual void onWindowRemovedTiling(CWindow*); - virtual bool isWindowTiled(CWindow*); - virtual void recalculateMonitor(const int&); - virtual void recalculateWindow(CWindow*); - virtual void resizeActiveWindow(const Vector2D&, CWindow* pWindow = nullptr); - virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool); - virtual std::any layoutMessage(SLayoutMessageHeader, std::string); - virtual SWindowRenderLayoutHints requestRenderHints(CWindow*); - virtual void switchWindows(CWindow*, CWindow*); - virtual void alterSplitRatio(CWindow*, float, bool); - virtual std::string getLayoutName(); - virtual void replaceWindowDataWith(CWindow* from, CWindow* to); - - virtual void onEnable(); - virtual void onDisable(); - - private: - std::vector m_vWindowData; -}; \ No newline at end of file diff --git a/example/examplePlugin/globals.hpp b/example/examplePlugin/globals.hpp deleted file mode 100644 index 22574754..00000000 --- a/example/examplePlugin/globals.hpp +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include - -inline HANDLE PHANDLE = nullptr; \ No newline at end of file diff --git a/example/examplePlugin/main.cpp b/example/examplePlugin/main.cpp deleted file mode 100644 index f2cd1075..00000000 --- a/example/examplePlugin/main.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#define WLR_USE_UNSTABLE - -#include "globals.hpp" - -#include -#include -#include "customLayout.hpp" -#include "customDecoration.hpp" - -#include -#include - -// Methods -inline std::unique_ptr g_pCustomLayout; -inline CFunctionHook* g_pFocusHook = nullptr; -inline CFunctionHook* g_pMotionHook = nullptr; -inline CFunctionHook* g_pMouseDownHook = nullptr; -typedef void (*origFocusWindow)(void*, CWindow*, wlr_surface*); -typedef void (*origMotion)(wlr_seat*, uint32_t, double, double); -typedef void (*origMouseDownNormal)(void*, wlr_pointer_button_event*); - -// Do NOT change this function. -APICALL EXPORT std::string PLUGIN_API_VERSION() { - return HYPRLAND_API_VERSION; -} - -static void onActiveWindowChange(void* self, std::any data) { - try { - auto* const PWINDOW = std::any_cast(data); - - HyprlandAPI::addNotification(PHANDLE, "[ExamplePlugin] Active window: " + (PWINDOW ? PWINDOW->m_szTitle : "None"), CColor{0.f, 0.5f, 1.f, 1.f}, 5000); - } catch (std::bad_any_cast& e) { HyprlandAPI::addNotification(PHANDLE, "[ExamplePlugin] Active window: None", CColor{0.f, 0.5f, 1.f, 1.f}, 5000); } -} - -static void onNewWindow(void* self, std::any data) { - auto* const PWINDOW = std::any_cast(data); - - HyprlandAPI::addWindowDecoration(PHANDLE, PWINDOW, new CCustomDecoration(PWINDOW)); -} - -void hkFocusWindow(void* thisptr, CWindow* pWindow, wlr_surface* pSurface) { - // HyprlandAPI::addNotification(PHANDLE, getFormat("FocusWindow with %lx %lx", pWindow, pSurface), CColor{0.f, 1.f, 1.f, 1.f}, 5000); - (*(origFocusWindow)g_pFocusHook->m_pOriginal)(thisptr, pWindow, pSurface); -} - -void hkNotifyMotion(wlr_seat* wlr_seat, uint32_t time_msec, double sx, double sy) { - // HyprlandAPI::addNotification(PHANDLE, getFormat("NotifyMotion with %lf %lf", sx, sy), CColor{0.f, 1.f, 1.f, 1.f}, 5000); - (*(origMotion)g_pMotionHook->m_pOriginal)(wlr_seat, time_msec, sx, sy); -} - -void hkProcessMouseDownNormal(void* thisptr, wlr_pointer_button_event* e) { - // HyprlandAPI::addNotification(PHANDLE, "Mouse down normal!", CColor{0.8f, 0.2f, 0.5f, 1.0f}, 5000); - (*(origMouseDownNormal)g_pMouseDownHook->m_pOriginal)(thisptr, e); -} - -APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { - PHANDLE = handle; - - HyprlandAPI::addNotification(PHANDLE, "Hello World from an example plugin!", CColor{0.f, 1.f, 1.f, 1.f}, 5000); - - HyprlandAPI::registerCallbackDynamic(PHANDLE, "activeWindow", [&](void* self, SCallbackInfo& info, std::any data) { onActiveWindowChange(self, data); }); - HyprlandAPI::registerCallbackDynamic(PHANDLE, "openWindow", [&](void* self, SCallbackInfo& info, std::any data) { onNewWindow(self, data); }); - - g_pCustomLayout = std::make_unique(); - - HyprlandAPI::addLayout(PHANDLE, "custom", g_pCustomLayout.get()); - - HyprlandAPI::addConfigValue(PHANDLE, "plugin:example:border_color", SConfigValue{.intValue = configStringToInt("rgb(44ee44)")}); - - HyprlandAPI::addDispatcher(PHANDLE, "example", [](std::string arg) { HyprlandAPI::addNotification(PHANDLE, "Arg passed: " + arg, CColor{0.5f, 0.5f, 0.7f, 1.0f}, 5000); }); - - // Hook a public member - g_pFocusHook = HyprlandAPI::createFunctionHook(PHANDLE, (void*)&CCompositor::focusWindow, (void*)&hkFocusWindow); - // Hook a public non-member - g_pMotionHook = HyprlandAPI::createFunctionHook(PHANDLE, (void*)&wlr_seat_pointer_notify_motion, (void*)&hkNotifyMotion); - // Hook a private member - static const auto METHODS = HyprlandAPI::findFunctionsByName(PHANDLE, "processMouseDownNormal"); - g_pMouseDownHook = HyprlandAPI::createFunctionHook(PHANDLE, METHODS[0].address, (void*)&hkProcessMouseDownNormal); - - static auto* const PBORDERCOLOR = HyprlandAPI::getConfigValue(PHANDLE, "plugin:example:border_color"); - - // fancy notifications - HyprlandAPI::addNotificationV2( - PHANDLE, - {{"text", "Example hint, color " + std::to_string(PBORDERCOLOR->intValue)}, {"time", (uint64_t)10000}, {"color", CColor{PBORDERCOLOR->intValue}}, {"icon", ICON_HINT}}); - - // Enable our hooks - g_pFocusHook->hook(); - g_pMotionHook->hook(); - g_pMouseDownHook->hook(); - - HyprlandAPI::reloadConfig(); - - return {"ExamplePlugin", "An example plugin", "Vaxry", "1.0"}; -} - -APICALL EXPORT void PLUGIN_EXIT() { - HyprlandAPI::invokeHyprctlCommand("seterror", "disable"); -} \ No newline at end of file From 3c33d4b9dda3c418a6b842c71720040b092f8510 Mon Sep 17 00:00:00 2001 From: dranull <150595692+dranull@users.noreply.github.com> Date: Tue, 2 Jan 2024 13:50:30 +0000 Subject: [PATCH 482/513] keybinds: Refocus only if the silently moved window had the focus (#4328) --- src/managers/KeybindManager.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index d379a408..21cc1f74 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1062,10 +1062,12 @@ void CKeybindManager::moveActiveToWorkspaceSilent(std::string args) { g_pCompositor->moveWindowToWorkspaceSafe(PWINDOW, pWorkspace); } - if (const auto PATCOORDS = g_pCompositor->vectorToWindowIdeal(OLDMIDDLE); PATCOORDS && PATCOORDS != PWINDOW) - g_pCompositor->focusWindow(PATCOORDS); - else - g_pInputManager->refocus(); + if (PWINDOW == g_pCompositor->m_pLastWindow) { + if (const auto PATCOORDS = g_pCompositor->vectorToWindowIdeal(OLDMIDDLE, PWINDOW); PATCOORDS) + g_pCompositor->focusWindow(PATCOORDS); + else + g_pInputManager->refocus(); + } } void CKeybindManager::moveFocusTo(std::string args) { From 4f26c4e1ebf868243dc628182c88d7feb52c8472 Mon Sep 17 00:00:00 2001 From: flicko <77581181+flick0@users.noreply.github.com> Date: Tue, 2 Jan 2024 21:08:30 +0530 Subject: [PATCH 483/513] config: variables update their value when set again (#4263) * variables update their value when set again * only sort if new variable is found * clang-format --- src/config/ConfigManager.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 28959128..44b5374b 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -395,10 +395,20 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s if (!COMMAND.starts_with("device:") /* devices parsed later */ && !COMMAND.starts_with("plugin:") /* plugins parsed later */) { if (COMMAND[0] == '$') { // register a dynamic var - Debug::log(LOG, "Registered dynamic var \"{}\" -> {}", COMMAND, VALUE); - configDynamicVars.emplace_back(std::make_pair<>(COMMAND.substr(1), VALUE)); + bool found = false; + for (auto& [var, val] : configDynamicVars) { + if (var == COMMAND.substr(1)) { + Debug::log(LOG, "Registered new value for dynamic var \"{}\" -> {}", COMMAND, VALUE); + val = VALUE; + found = true; + } + } - std::sort(configDynamicVars.begin(), configDynamicVars.end(), [&](const auto& a, const auto& b) { return a.first.length() > b.first.length(); }); + if (!found) { + Debug::log(LOG, "Registered dynamic var \"{}\" -> {}", COMMAND, VALUE); + configDynamicVars.emplace_back(std::make_pair<>(COMMAND.substr(1), VALUE)); + std::sort(configDynamicVars.begin(), configDynamicVars.end(), [&](const auto& a, const auto& b) { return a.first.length() > b.first.length(); }); + } } else { parseError = "Error setting value <" + VALUE + "> for field <" + COMMAND + ">: No such field."; } From 1512b81126dd115f089fd21244692d92034c78f8 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 2 Jan 2024 22:18:30 +0100 Subject: [PATCH 484/513] master: guard PNODE in roll* fixes #4331 --- src/layout/MasterLayout.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 63389c3a..2506bbf2 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -1331,6 +1331,9 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri const auto PWINDOW = header.pWindow; const auto PNODE = getNodeFromWindow(PWINDOW); + if (!PNODE) + return 0; + const auto OLDMASTER = PNODE->isMaster ? PNODE : getMasterNodeOnWorkspace(PNODE->workspaceID); const auto OLDMASTERIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *OLDMASTER); @@ -1353,6 +1356,9 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri const auto PWINDOW = header.pWindow; const auto PNODE = getNodeFromWindow(PWINDOW); + if (!PNODE) + return 0; + const auto OLDMASTER = PNODE->isMaster ? PNODE : getMasterNodeOnWorkspace(PNODE->workspaceID); const auto OLDMASTERIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *OLDMASTER); From 4d6d662c67786c86647cf41b5b20d9c0b418dbb3 Mon Sep 17 00:00:00 2001 From: rszyma Date: Thu, 4 Jan 2024 10:20:17 +0100 Subject: [PATCH 485/513] Makefile: force ln command to overwrite symlink (#4347) When running `make install` twice ln shows an error: ``` ln -s -r /usr/local/bin/Hyprland /usr/local/bin/hyprland ln: failed to create symbolic link '/usr/local/bin/hyprland': File exists ``` --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a0b00259..ecfb30f1 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ install: chmod 755 ${PREFIX}/bin/Hyprland chmod 755 ${PREFIX}/bin/hyprctl chmod 755 ${PREFIX}/bin/hyprpm - ln -s -r ${PREFIX}/bin/Hyprland ${PREFIX}/bin/hyprland + ln -s -r -f ${PREFIX}/bin/Hyprland ${PREFIX}/bin/hyprland if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi mkdir -p ${PREFIX}/share/hyprland cp ./assets/wall_* ${PREFIX}/share/hyprland From 880996b05339ba87066958a517885f1941185269 Mon Sep 17 00:00:00 2001 From: thejch <66577496+thejch@users.noreply.github.com> Date: Thu, 4 Jan 2024 07:17:17 -0800 Subject: [PATCH 486/513] master: Add more null checks for rollnext (#4343) * add more null check for rollnext * remove pwindow check --- src/layout/MasterLayout.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 2506bbf2..9a76801c 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -1334,7 +1334,10 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri if (!PNODE) return 0; - const auto OLDMASTER = PNODE->isMaster ? PNODE : getMasterNodeOnWorkspace(PNODE->workspaceID); + const auto OLDMASTER = PNODE->isMaster ? PNODE : getMasterNodeOnWorkspace(PNODE->workspaceID); + if (!OLDMASTER) + return 0; + const auto OLDMASTERIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *OLDMASTER); for (auto& nd : m_lMasterNodesData) { @@ -1359,7 +1362,10 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri if (!PNODE) return 0; - const auto OLDMASTER = PNODE->isMaster ? PNODE : getMasterNodeOnWorkspace(PNODE->workspaceID); + const auto OLDMASTER = PNODE->isMaster ? PNODE : getMasterNodeOnWorkspace(PNODE->workspaceID); + if (!OLDMASTER) + return 0; + const auto OLDMASTERIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *OLDMASTER); for (auto& nd : m_lMasterNodesData | std::views::reverse) { From aeeeace102c14ea0ab4df6840ee225e1b14ea970 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Thu, 4 Jan 2024 22:52:00 +0200 Subject: [PATCH 487/513] flake.lock: update --- flake.lock | 47 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index 85a83ff8..1619129f 100644 --- a/flake.lock +++ b/flake.lock @@ -23,13 +23,47 @@ "type": "github" } }, + "hyprlang": { + "inputs": { + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1704287638, + "narHash": "sha256-TuRXJGwtK440AXQNl5eiqmQqY4LZ/9+z/R7xC0ie3iA=", + "owner": "hyprwm", + "repo": "hyprlang", + "rev": "6624f2bb66d4d27975766e81f77174adbe58ec97", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprlang", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1703438236, - "narHash": "sha256-aqVBq1u09yFhL7bj1/xyUeJjzr92fXVvQSSEx6AdB1M=", + "lastModified": 1704194953, + "narHash": "sha256-RtDKd8Mynhe5CFnVT8s0/0yqtWFMM9LmCzXv/YKxnq4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5f64a12a728902226210bf01d25ec6cbb9d9265b", + "rev": "bd645e8668ec6612439a9ee7e71f7eac4099d4f6", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1702645756, + "narHash": "sha256-qKI6OR3TYJYQB3Q8mAZ+DG4o/BR9ptcv9UnRV2hzljc=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "40c3c94c241286dd2243ea34d3aef8a488f9e4d0", "type": "github" }, "original": { @@ -87,6 +121,7 @@ "hyprland-protocols": [ "hyprland-protocols" ], + "hyprlang": "hyprlang", "nixpkgs": [ "nixpkgs" ], @@ -95,11 +130,11 @@ ] }, "locked": { - "lastModified": 1703514399, - "narHash": "sha256-VRr5Xc4S/VPr/gU3fiOD3vSIL2+GJ+LUrmFTWTwnTz4=", + "lastModified": 1704400467, + "narHash": "sha256-IsEAKBCorRlN53FwFAMbyGLRsPVu/ZrWEJtCwykPds8=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "0a318a7a217a6402b0b705837cd5b50b0e94b31b", + "rev": "1c802128f6cc3db29a8ef01552b1a22f894eeefd", "type": "github" }, "original": { From d3acf8da3be048647d19251dcceaed470c199cd2 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Fri, 5 Jan 2024 12:40:13 +0100 Subject: [PATCH 488/513] CI: don't close stale issues --- .github/workflows/stale.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 8955517f..51f6b91e 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -25,3 +25,4 @@ jobs: stale-issue-label: 'stale' stale-pr-label: 'stale' operations-per-run: 40 + days-before-close: -1 From d8dbdc4a017e051b3dde2e93791e2495722bfa21 Mon Sep 17 00:00:00 2001 From: Naksu <53827613+naksudev@users.noreply.github.com> Date: Fri, 5 Jan 2024 12:45:49 +0100 Subject: [PATCH 489/513] main: Fix typo in std::cerr (#4359) --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 2edf3601..e1f43ad0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -85,7 +85,7 @@ int main(int argc, char** argv) { } if (!ignoreSudo && Init::isSudo()) { - std::cerr << "[ ERROR ] Hyprland was launched with superuser priveleges, but the privileges check is not omitted.\n"; + std::cerr << "[ ERROR ] Hyprland was launched with superuser privileges, but the privileges check is not omitted.\n"; std::cerr << " Hint: Use the --i-am-really-stupid flag to omit that check.\n"; return 1; From 7e033e48ace5406a9bc442f7d403f9ce3af193f3 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Fri, 5 Jan 2024 17:57:24 +0100 Subject: [PATCH 490/513] make: unbreak with non-GNU ln(1) after 78f9ba9fdd7e ln -s -r -f /usr/local/bin/Hyprland /usr/local/bin/hyprland ln: illegal option -- r usage: ln [-s [-F] | -L | -P] [-f | -i] [-hnv] source_file [target_file] ln [-s [-F] | -L | -P] [-f | -i] [-hnv] source_file ... target_dir link source_file target_file *** Error code 1 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ecfb30f1..e3224970 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ install: chmod 755 ${PREFIX}/bin/Hyprland chmod 755 ${PREFIX}/bin/hyprctl chmod 755 ${PREFIX}/bin/hyprpm - ln -s -r -f ${PREFIX}/bin/Hyprland ${PREFIX}/bin/hyprland + cd ${PREFIX}/bin && ln -sf Hyprland hyprland if [ ! -f ${PREFIX}/share/wayland-sessions/hyprland.desktop ]; then cp ./example/hyprland.desktop ${PREFIX}/share/wayland-sessions; fi mkdir -p ${PREFIX}/share/hyprland cp ./assets/wall_* ${PREFIX}/share/hyprland From 666ee61c13e67e3a6943cd96157d9fb0967e596a Mon Sep 17 00:00:00 2001 From: Epilepsy Gatherings <73647246+phonetic112@users.noreply.github.com> Date: Sun, 7 Jan 2024 06:06:33 -0500 Subject: [PATCH 491/513] input: leave special on focus (#4358) --- src/Compositor.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index af03e025..f3efad86 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -928,12 +928,13 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) { if (pWindow->m_bPinned) pWindow->m_iWorkspaceID = m_pLastMonitor->activeWorkspace; + const auto PMONITOR = getMonitorFromID(pWindow->m_iMonitorID); + if (!isWorkspaceVisible(pWindow->m_iWorkspaceID)) { + const auto PWORKSPACE = getWorkspaceByID(pWindow->m_iWorkspaceID); // This is to fix incorrect feedback on the focus history. - const auto PWORKSPACE = getWorkspaceByID(pWindow->m_iWorkspaceID); PWORKSPACE->m_pLastFocusedWindow = pWindow; PWORKSPACE->rememberPrevWorkspace(getWorkspaceByID(m_pLastMonitor->activeWorkspace)); - const auto PMONITOR = getMonitorFromID(PWORKSPACE->m_iMonitorID); PMONITOR->changeWorkspace(PWORKSPACE, false, true); // changeworkspace already calls focusWindow return; @@ -942,6 +943,9 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) { const auto PLASTWINDOW = m_pLastWindow; m_pLastWindow = pWindow; + if (PMONITOR->specialWorkspaceID && PMONITOR->specialWorkspaceID != pWindow->m_iWorkspaceID) + PMONITOR->setSpecialWorkspace(nullptr); + // we need to make the PLASTWINDOW not equal to m_pLastWindow so that RENDERDATA is correct for an unfocused window if (windowValidMapped(PLASTWINDOW)) { PLASTWINDOW->updateDynamicRules(); From 7904188de9ca631436484cde733ef871f518d962 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 7 Jan 2024 14:04:25 +0100 Subject: [PATCH 492/513] input: allow focusSurface when locked if surfase is sessionLock --- src/Compositor.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index f3efad86..b98c714d 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1019,10 +1019,8 @@ void CCompositor::focusSurface(wlr_surface* pSurface, CWindow* pWindowOwner) { if (m_sSeat.seat->keyboard_state.focused_surface == pSurface || (pWindowOwner && m_sSeat.seat->keyboard_state.focused_surface == pWindowOwner->m_pWLSurface.wlr())) return; // Don't focus when already focused on this. - if (g_pSessionLockManager->isSessionLocked()) { - wlr_seat_keyboard_clear_focus(m_sSeat.seat); - m_pLastFocus = nullptr; - } + if (g_pSessionLockManager->isSessionLocked() && !g_pSessionLockManager->isSurfaceSessionLock(pSurface)) + return; // Unfocus last surface if should if (m_pLastFocus && !pWindowOwner) From 9f2bde925bde09b4820a2cef369e9ddd930a746b Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 7 Jan 2024 18:15:51 +0100 Subject: [PATCH 493/513] hyprpm: handle failed compilations gracefully --- hyprpm/src/core/DataState.cpp | 11 +++++++++-- hyprpm/src/core/Manifest.hpp | 1 + hyprpm/src/core/Plugin.hpp | 3 ++- hyprpm/src/core/PluginManager.cpp | 17 ++++++++++++----- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/hyprpm/src/core/DataState.cpp b/hyprpm/src/core/DataState.cpp index d95f10bb..724c40ac 100644 --- a/hyprpm/src/core/DataState.cpp +++ b/hyprpm/src/core/DataState.cpp @@ -47,7 +47,8 @@ void DataState::addNewPluginRepo(const SPluginRepository& repo) { DATA.emplace(p.name, toml::table{ {"filename", p.name + ".so"}, - {"enabled", p.enabled} + {"enabled", p.enabled}, + {"failed", p.failed} }); } // clang-format on @@ -172,9 +173,10 @@ std::vector DataState::getAllRepositories() { continue; const auto ENABLED = STATE[key]["enabled"].value_or(false); + const auto FAILED = STATE[key]["failed"].value_or(false); const auto FILENAME = STATE[key]["filename"].value_or(""); - repo.plugins.push_back(SPlugin{std::string{key.str()}, FILENAME, ENABLED}); + repo.plugins.push_back(SPlugin{std::string{key.str()}, FILENAME, ENABLED, FAILED}); } repos.push_back(repo); @@ -201,6 +203,11 @@ bool DataState::setPluginEnabled(const std::string& name, bool enabled) { if (key.str() != name) continue; + const auto FAILED = STATE[key]["failed"].value_or(false); + + if (FAILED) + return false; + (*STATE[key].as_table()).insert_or_assign("enabled", enabled); std::ofstream state(entry.path().string() + "/state.toml", std::ios::trunc); diff --git a/hyprpm/src/core/Manifest.hpp b/hyprpm/src/core/Manifest.hpp index 63e1791f..55b4a7f0 100644 --- a/hyprpm/src/core/Manifest.hpp +++ b/hyprpm/src/core/Manifest.hpp @@ -19,6 +19,7 @@ class CManifest { std::vector authors; std::vector buildSteps; std::string output; + bool failed = false; }; struct { diff --git a/hyprpm/src/core/Plugin.hpp b/hyprpm/src/core/Plugin.hpp index 32c02a49..a69478d1 100644 --- a/hyprpm/src/core/Plugin.hpp +++ b/hyprpm/src/core/Plugin.hpp @@ -6,7 +6,8 @@ struct SPlugin { std::string name; std::string filename; - bool enabled; + bool enabled = false; + bool failed = false; }; struct SPluginRepository { diff --git a/hyprpm/src/core/PluginManager.cpp b/hyprpm/src/core/PluginManager.cpp index 3c091242..4cc93d4b 100644 --- a/hyprpm/src/core/PluginManager.cpp +++ b/hyprpm/src/core/PluginManager.cpp @@ -195,12 +195,14 @@ bool CPluginManager::addNewPluginRepo(const std::string& url) { } if (!std::filesystem::exists("/tmp/hyprpm/new/" + p.output)) { - std::cerr << "\n" << Colors::RED << "✖" << Colors::RESET << " Plugin " << p.name << " failed to build.\n"; + progress.printMessageAbove(std::string{Colors::RED} + "✖" + Colors::RESET + " Plugin " + p.name + " failed to build.\n"); if (m_bVerbose) std::cout << Colors::BLUE << "[v] " << Colors::RESET << "shell returned: " << out << "\n"; - return false; + p.failed = true; + + continue; } progress.printMessageAbove(std::string{Colors::GREEN} + "✔" + Colors::RESET + " built " + p.name + " into " + p.output); @@ -220,7 +222,7 @@ bool CPluginManager::addNewPluginRepo(const std::string& url) { repo.url = url; repo.hash = repohash; for (auto& p : pManifest->m_vPlugins) { - repo.plugins.push_back(SPlugin{p.name, "/tmp/hyprpm/new/" + p.output, false}); + repo.plugins.push_back(SPlugin{p.name, "/tmp/hyprpm/new/" + p.output, false, p.failed}); } DataState::addNewPluginRepo(repo); @@ -696,8 +698,13 @@ void CPluginManager::listAllPlugins() { std::cout << std::string{Colors::RESET} + " → Repository " + r.name + ":\n"; for (auto& p : r.plugins) { - std::cout << std::string{Colors::RESET} + " │ Plugin " + p.name + "\n └─ enabled: " << (p.enabled ? Colors::GREEN : Colors::RED) << (p.enabled ? "true" : "false") - << Colors::RESET << "\n"; + + std::cout << std::string{Colors::RESET} + " │ Plugin " + p.name; + + if (!p.failed) + std::cout << "\n └─ enabled: " << (p.enabled ? Colors::GREEN : Colors::RED) << (p.enabled ? "true" : "false") << Colors::RESET << "\n"; + else + std::cout << "\n └─ enabled: " << Colors::RED << "Plugin failed to build" << Colors::RESET << "\n"; } } } From 44ee9915e34910aac67ab60f1296eed8be8e7cea Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 7 Jan 2024 18:35:44 +0100 Subject: [PATCH 494/513] renderer: overhaul renderModifData --- src/helpers/Box.hpp | 2 ++ src/render/OpenGL.cpp | 38 ++++++++++++++++++++++++++++++-------- src/render/OpenGL.hpp | 13 +++++++++++-- src/render/Renderer.cpp | 16 ++++++++++------ 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/src/helpers/Box.hpp b/src/helpers/Box.hpp index 5cb7f17f..a1ed83be 100644 --- a/src/helpers/Box.hpp +++ b/src/helpers/Box.hpp @@ -73,6 +73,8 @@ class CBox { double height; }; + double rot = 0; /* rad, ccw */ + // bool operator==(const CBox& rhs) const { return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index cb468932..c6d16dd8 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -637,7 +637,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion TRACY_GPU_ZONE("RenderRectWithDamage"); CBox newBox = *box; - newBox.scale(m_RenderData.renderModif.scale).translate(m_RenderData.renderModif.translate); + m_RenderData.renderModif.applyToBox(newBox); box = &newBox; @@ -723,7 +723,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox* return; CBox newBox = *pBox; - newBox.scale(m_RenderData.renderModif.scale).translate(m_RenderData.renderModif.translate); + m_RenderData.renderModif.applyToBox(newBox); static auto* const PDIMINACTIVE = &g_pConfigManager->getConfigValuePtr("decoration:dim_inactive")->intValue; @@ -886,7 +886,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, CBox* pBox) { return; CBox newBox = *pBox; - newBox.scale(m_RenderData.renderModif.scale).translate(m_RenderData.renderModif.translate); + m_RenderData.renderModif.applyToBox(newBox); // get transform const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); @@ -940,7 +940,7 @@ void CHyprOpenGLImpl::renderTextureMatte(const CTexture& tex, CBox* pBox, CFrame return; CBox newBox = *pBox; - newBox.scale(m_RenderData.renderModif.scale).translate(m_RenderData.renderModif.translate); + m_RenderData.renderModif.applyToBox(newBox); // get transform const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); @@ -1475,14 +1475,14 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in return; CBox newBox = *box; - newBox.scale(m_RenderData.renderModif.scale).translate(m_RenderData.renderModif.translate); + m_RenderData.renderModif.applyToBox(newBox); box = &newBox; if (borderSize < 1) return; - int scaledBorderSize = std::round(borderSize * m_RenderData.pMonitor->scale * m_RenderData.renderModif.scale); + int scaledBorderSize = std::round(borderSize * m_RenderData.pMonitor->scale); // adjust box box->x -= scaledBorderSize; @@ -1779,7 +1779,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const TRACY_GPU_ZONE("RenderShadow"); CBox newBox = *box; - newBox.scale(m_RenderData.renderModif.scale).translate(m_RenderData.renderModif.translate); + m_RenderData.renderModif.applyToBox(newBox); box = &newBox; @@ -2210,4 +2210,26 @@ const SGLPixelFormat* CHyprOpenGLImpl::getPixelFormatFromDRM(uint32_t drmFormat) } return nullptr; -} \ No newline at end of file +} + +void SRenderModifData::applyToBox(CBox& box) { + for (auto& [type, val] : modifs) { + try { + switch (type) { + case RMOD_TYPE_SCALE: box.scale(std::any_cast(val)); break; + case RMOD_TYPE_SCALECENTER: box.scaleFromCenter(std::any_cast(val)); break; + case RMOD_TYPE_TRANSLATE: box.translate(std::any_cast(val)); break; + case RMOD_TYPE_ROTATE: box.rot += std::any_cast(val); break; + case RMOD_TYPE_ROTATECENTER: { + const auto THETA = std::any_cast(val); + const double COS = std::cos(THETA); + const double SIN = std::sin(THETA); + box.rot += THETA; + const auto OLDPOS = box.pos(); + box.x = OLDPOS.x * COS - OLDPOS.y * SIN; + box.y = OLDPOS.y * COS + OLDPOS.x * SIN; + } + } + } catch (std::bad_any_cast& e) { Debug::log(ERR, "BUG THIS OR PLUGIN ERROR: caught a bad_any_cast in SRenderModifData::applyToBox!"); } + } +} diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index cd52fe3e..ba27b608 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -36,8 +36,17 @@ enum eDiscardMode { }; struct SRenderModifData { - Vector2D translate = {}; - float scale = 1.f; + enum eRenderModifType { + RMOD_TYPE_SCALE, /* scale by a float */ + RMOD_TYPE_SCALECENTER, /* scale by a float from the center */ + RMOD_TYPE_TRANSLATE, /* translate by a Vector2D */ + RMOD_TYPE_ROTATE, /* rotate by a float in rad from top left */ + RMOD_TYPE_ROTATECENTER, /* rotate by a float in rad from center */ + }; + + std::vector> modifs; + + void applyToBox(CBox& box); }; struct SGLPixelFormat { diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 533215ce..16607739 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -653,13 +653,17 @@ void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, CMon } void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, CWorkspace* pWorkspace, timespec* time, const Vector2D& translate, const float& scale) { - static auto* const PDIMSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:dim_special")->floatValue; - static auto* const PBLURSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:blur:special")->intValue; - static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue; - static auto* const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue; - static auto* const PBACKGROUNDCOLOR = &g_pConfigManager->getConfigValuePtr("misc:background_color")->intValue; + static auto* const PDIMSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:dim_special")->floatValue; + static auto* const PBLURSPECIAL = &g_pConfigManager->getConfigValuePtr("decoration:blur:special")->intValue; + static auto* const PBLUR = &g_pConfigManager->getConfigValuePtr("decoration:blur:enabled")->intValue; + static auto* const PRENDERTEX = &g_pConfigManager->getConfigValuePtr("misc:disable_hyprland_logo")->intValue; + static auto* const PBACKGROUNDCOLOR = &g_pConfigManager->getConfigValuePtr("misc:background_color")->intValue; - const SRenderModifData RENDERMODIFDATA = {translate, scale}; + SRenderModifData RENDERMODIFDATA; + if (translate != Vector2D{0, 0}) + RENDERMODIFDATA.modifs.push_back({SRenderModifData::eRenderModifType::RMOD_TYPE_TRANSLATE, translate}); + if (scale != 1.f) + RENDERMODIFDATA.modifs.push_back({SRenderModifData::eRenderModifType::RMOD_TYPE_SCALE, scale}); if (!pMonitor) return; From f5b2fd2bc36b35850502640d18281350e953b70d Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 7 Jan 2024 18:37:02 +0100 Subject: [PATCH 495/513] opengl: add renderdata.forceIntrospection --- src/render/OpenGL.cpp | 10 ++++++---- src/render/OpenGL.hpp | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index c6d16dd8..ffc899fe 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -232,7 +232,8 @@ void CHyprOpenGLImpl::begin(CMonitor* pMonitor, CRegion* pDamage, CFramebuffer* const auto PRBO = g_pHyprRenderer->getCurrentRBO(); const bool FBPROPERSIZE = fb && fb->m_vSize == pMonitor->vecPixelSize; - if (!FBPROPERSIZE || m_sFinalScreenShader.program > 0 || (PRBO && pMonitor->vecPixelSize != PRBO->getFB()->m_vSize) || passRequiresIntrospection(pMonitor)) { + if (m_RenderData.forceIntrospection || !FBPROPERSIZE || m_sFinalScreenShader.program > 0 || (PRBO && pMonitor->vecPixelSize != PRBO->getFB()->m_vSize) || + passRequiresIntrospection(pMonitor)) { // we have to offload // bind the offload Hypr Framebuffer m_RenderData.pCurrentMonData->offloadFB.bind(); @@ -307,9 +308,10 @@ void CHyprOpenGLImpl::end() { } // reset our data - m_RenderData.pMonitor = nullptr; - m_RenderData.mouseZoomFactor = 1.f; - m_RenderData.mouseZoomUseMouse = true; + m_RenderData.pMonitor = nullptr; + m_RenderData.mouseZoomFactor = 1.f; + m_RenderData.mouseZoomUseMouse = true; + m_RenderData.forceIntrospection = false; } void CHyprOpenGLImpl::initShaders() { diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index ba27b608..9fd6d197 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -108,6 +108,7 @@ struct SCurrentRenderData { float mouseZoomFactor = 1.f; bool mouseZoomUseMouse = true; // true by default bool useNearestNeighbor = false; + bool forceIntrospection = false; // cleaned in ::end() Vector2D primarySurfaceUVTopLeft = Vector2D(-1, -1); Vector2D primarySurfaceUVBottomRight = Vector2D(-1, -1); From d7d333d162da2d3fc852b2c7a3faa2709440cefa Mon Sep 17 00:00:00 2001 From: vaxerski Date: Sun, 7 Jan 2024 18:51:08 +0100 Subject: [PATCH 496/513] opengl: apply box rot to projections --- src/render/OpenGL.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index ffc899fe..2dd4ca0e 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -644,7 +644,7 @@ void CHyprOpenGLImpl::renderRectWithDamage(CBox* box, const CColor& col, CRegion box = &newBox; float matrix[9]; - wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, + wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), newBox.rot, m_RenderData.pMonitor->projMatrix.data()); // TODO: write own, don't use WLR here float glMatrix[9]; @@ -732,7 +732,7 @@ void CHyprOpenGLImpl::renderTextureInternalWithDamage(const CTexture& tex, CBox* // get transform const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); float matrix[9]; - wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->projMatrix.data()); + wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, newBox.rot, m_RenderData.pMonitor->projMatrix.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -893,7 +893,7 @@ void CHyprOpenGLImpl::renderTexturePrimitive(const CTexture& tex, CBox* pBox) { // get transform const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); float matrix[9]; - wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->projMatrix.data()); + wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, newBox.rot, m_RenderData.pMonitor->projMatrix.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -947,7 +947,7 @@ void CHyprOpenGLImpl::renderTextureMatte(const CTexture& tex, CBox* pBox, CFrame // get transform const auto TRANSFORM = wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform); float matrix[9]; - wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, 0, m_RenderData.pMonitor->projMatrix.data()); + wlr_matrix_project_box(matrix, newBox.pWlr(), TRANSFORM, newBox.rot, m_RenderData.pMonitor->projMatrix.data()); float glMatrix[9]; wlr_matrix_multiply(glMatrix, m_RenderData.projection, matrix); @@ -1495,7 +1495,7 @@ void CHyprOpenGLImpl::renderBorder(CBox* box, const CGradientValueData& grad, in round += round == 0 ? 0 : scaledBorderSize; float matrix[9]; - wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, + wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), newBox.rot, m_RenderData.pMonitor->projMatrix.data()); // TODO: write own, don't use WLR here float glMatrix[9]; @@ -1792,7 +1792,7 @@ void CHyprOpenGLImpl::renderRoundedShadow(CBox* box, int round, int range, const const auto col = color; float matrix[9]; - wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), 0, + wlr_matrix_project_box(matrix, box->pWlr(), wlr_output_transform_invert(!m_bEndFrame ? WL_OUTPUT_TRANSFORM_NORMAL : m_RenderData.pMonitor->transform), newBox.rot, m_RenderData.pMonitor->projMatrix.data()); // TODO: write own, don't use WLR here float glMatrix[9]; From 955009655d56fc35e75c71535fefc5a5c7b31071 Mon Sep 17 00:00:00 2001 From: Piroro-hs Date: Tue, 9 Jan 2024 03:24:52 +0900 Subject: [PATCH 497/513] cmake: Propagate NO_XWAYLAND to wlroots building setup (#4385) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 88e094a7..f894212c 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,7 @@ ExternalProject_Add( PREFIX ${CMAKE_SOURCE_DIR}/subprojects/wlroots SOURCE_DIR ${CMAKE_SOURCE_DIR}/subprojects/wlroots PATCH_COMMAND sed -E -i -e "s/(soversion = .*$)/soversion = 13032/g" meson.build - CONFIGURE_COMMAND meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $,-Db_sanitize=address,-Db_sanitize=none> && meson setup build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dexamples=false -Drenderers=gles2 $,-Db_sanitize=address,-Db_sanitize=none> --reconfigure + CONFIGURE_COMMAND meson setup --reconfigure build --buildtype=${BUILDTYPE_LOWER} -Dwerror=false -Dxwayland=$,disabled,enabled> -Dexamples=false -Drenderers=gles2 $,-Db_sanitize=address,-Db_sanitize=none> BUILD_COMMAND ninja -C build BUILD_ALWAYS true BUILD_IN_SOURCE true From 2ba2c8aeeee02d022882c825baa71243e1cb1e5d Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Mon, 8 Jan 2024 18:38:22 +0000 Subject: [PATCH 498/513] groupbar: improve gradient handling (#4390) modified: src/render/decorations/CHyprGroupBarDecoration.cpp --- .../decorations/CHyprGroupBarDecoration.cpp | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 61409256..4569337a 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -243,7 +243,7 @@ CTitleTex::~CTitleTex() { tex.destroyTexture(); } -void renderGradientTo(CTexture& tex, const CColor& grad) { +void renderGradientTo(CTexture& tex, CGradientValueData* grad) { if (!g_pCompositor->m_pLastMonitor) return; @@ -261,8 +261,12 @@ void renderGradientTo(CTexture& tex, const CColor& grad) { cairo_pattern_t* pattern; pattern = cairo_pattern_create_linear(0, 0, 0, bufferSize.y); - cairo_pattern_add_color_stop_rgba(pattern, 1, grad.r, grad.g, grad.b, grad.a); - cairo_pattern_add_color_stop_rgba(pattern, 0, grad.r, grad.g, grad.b, 0); + + for (unsigned long i = 0; i < grad->m_vColors.size(); i++) { + cairo_pattern_add_color_stop_rgba(pattern, 1 - (double)(i + 1) / (grad->m_vColors.size() + 1), grad->m_vColors[i].r, grad->m_vColors[i].g, grad->m_vColors[i].b, + grad->m_vColors[i].a); + } + cairo_rectangle(CAIRO, 0, 0, bufferSize.x, bufferSize.y); cairo_set_source(CAIRO, pattern); cairo_fill(CAIRO); @@ -290,13 +294,13 @@ void renderGradientTo(CTexture& tex, const CColor& grad) { } void refreshGroupBarGradients() { - static auto* const PGRADIENTS = &g_pConfigManager->getConfigValuePtr("group:groupbar:enabled")->intValue; - static auto* const PENABLED = &g_pConfigManager->getConfigValuePtr("group:groupbar:gradients")->intValue; + static auto* const PGRADIENTS = &g_pConfigManager->getConfigValuePtr("group:groupbar:enabled")->intValue; + static auto* const PENABLED = &g_pConfigManager->getConfigValuePtr("group:groupbar:gradients")->intValue; - static auto* const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.active")->data; - static auto* const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.inactive")->data; - static auto* const PGROUPCOLACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_active")->data; - static auto* const PGROUPCOLINACTIVELOCKED = &g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_inactive")->data; + CGradientValueData* PGROUPCOLACTIVE = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:groupbar:col.active")->data.get(); + CGradientValueData* PGROUPCOLINACTIVE = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:groupbar:col.inactive")->data.get(); + CGradientValueData* PGROUPCOLACTIVELOCKED = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_active")->data.get(); + CGradientValueData* PGROUPCOLINACTIVELOCKED = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("group:groupbar:col.locked_inactive")->data.get(); g_pHyprRenderer->makeEGLCurrent(); @@ -310,10 +314,10 @@ void refreshGroupBarGradients() { if (!*PENABLED || !*PGRADIENTS) return; - renderGradientTo(m_tGradientActive, ((CGradientValueData*)PGROUPCOLACTIVE->get())->m_vColors[0]); - renderGradientTo(m_tGradientInactive, ((CGradientValueData*)PGROUPCOLINACTIVE->get())->m_vColors[0]); - renderGradientTo(m_tGradientLockedActive, ((CGradientValueData*)PGROUPCOLACTIVELOCKED->get())->m_vColors[0]); - renderGradientTo(m_tGradientLockedInactive, ((CGradientValueData*)PGROUPCOLINACTIVELOCKED->get())->m_vColors[0]); + renderGradientTo(m_tGradientActive, PGROUPCOLACTIVE); + renderGradientTo(m_tGradientInactive, PGROUPCOLINACTIVE); + renderGradientTo(m_tGradientLockedActive, PGROUPCOLACTIVELOCKED); + renderGradientTo(m_tGradientLockedInactive, PGROUPCOLINACTIVELOCKED); } bool CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) { From f92a86af5367778a752ac2a0e9b32afc2e10fe2f Mon Sep 17 00:00:00 2001 From: vaxerski Date: Mon, 8 Jan 2024 19:58:15 +0100 Subject: [PATCH 499/513] renderer: ignore box offsets for fullscreen windows --- src/render/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 16607739..22613b4f 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -453,7 +453,7 @@ void CHyprRenderer::renderWindow(CWindow* pWindow, CMonitor* pMonitor, timespec* // clip box for animated offsets const Vector2D PREOFFSETPOS = {renderdata.x, renderdata.y}; - if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bPinned) { + if (!ignorePosition && pWindow->m_bIsFloating && !pWindow->m_bPinned && !pWindow->m_bIsFullscreen) { Vector2D offset; if (PWORKSPACE->m_vRenderOffset.vec().x != 0) { From 252aaaecfa3b57eb07822177a8bf3b609aff7115 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 9 Jan 2024 13:17:55 +0100 Subject: [PATCH 500/513] input: add special_fallthrough fixes #4323 --- src/Compositor.cpp | 17 ++++++++++++++--- src/config/ConfigManager.cpp | 1 + 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index b98c714d..62903cf9 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -654,6 +654,7 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos, CWindow* pIgnoreW static auto* const PRESIZEONBORDER = &g_pConfigManager->getConfigValuePtr("general:resize_on_border")->intValue; static auto* const PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue; static auto* const PBORDERGRABEXTEND = &g_pConfigManager->getConfigValuePtr("general:extend_border_grab_area")->intValue; + static auto* const PSPECIALFALLTHRU = &g_pConfigManager->getConfigValuePtr("input:special_fallthrough")->intValue; const auto BORDER_GRAB_AREA = *PRESIZEONBORDER ? *PBORDERSIZE + *PBORDERGRABEXTEND : 0; // pinned windows on top of floating regardless @@ -735,9 +736,16 @@ CWindow* CCompositor::vectorToWindowIdeal(const Vector2D& pos, CWindow* pIgnoreW }; // special workspace - if (PMONITOR->specialWorkspaceID) + if (PMONITOR->specialWorkspaceID && !*PSPECIALFALLTHRU) return windowForWorkspace(true); + if (PMONITOR->specialWorkspaceID) { + const auto PWINDOW = windowForWorkspace(true); + + if (PWINDOW) + return PWINDOW; + } + return windowForWorkspace(false); } @@ -876,7 +884,8 @@ CMonitor* CCompositor::getMonitorFromOutput(wlr_output* out) { void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) { - static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; + static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; + static auto* const PSPECIALFALLTHROUGH = &g_pConfigManager->getConfigValuePtr("input:special_fallthrough")->intValue; if (g_pCompositor->m_sSeat.exclusiveClient) { Debug::log(LOG, "Disallowing setting focus to a window due to there being an active input inhibitor layer."); @@ -943,7 +952,9 @@ void CCompositor::focusWindow(CWindow* pWindow, wlr_surface* pSurface) { const auto PLASTWINDOW = m_pLastWindow; m_pLastWindow = pWindow; - if (PMONITOR->specialWorkspaceID && PMONITOR->specialWorkspaceID != pWindow->m_iWorkspaceID) + /* If special fallthrough is enabled, this behavior will be disabled, as I have no better idea of nicely tracking which + window focuses are "via keybinds" and which ones aren't. */ + if (PMONITOR->specialWorkspaceID && PMONITOR->specialWorkspaceID != pWindow->m_iWorkspaceID && !*PSPECIALFALLTHROUGH) PMONITOR->setSpecialWorkspace(nullptr); // we need to make the PLASTWINDOW not equal to m_pLastWindow so that RENDERDATA is correct for an unfocused window diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 44b5374b..69128c52 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -223,6 +223,7 @@ void CConfigManager::setDefaultVars() { configValues["input:follow_mouse"].intValue = 1; configValues["input:mouse_refocus"].intValue = 1; + configValues["input:special_fallthrough"].intValue = 0; configValues["input:sensitivity"].floatValue = 0.f; configValues["input:accel_profile"].strValue = STRVAL_EMPTY; configValues["input:kb_file"].strValue = STRVAL_EMPTY; From 71166ef40b5f7640fcddb1951d84f0f086e198d2 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 9 Jan 2024 18:14:08 +0100 Subject: [PATCH 501/513] subsurfaceTree: update surface tree protocol feedback on map --- src/Window.cpp | 14 ++++++++------ src/Window.hpp | 2 +- src/events/Monitors.cpp | 2 +- src/events/Windows.cpp | 2 +- src/helpers/Monitor.cpp | 2 +- src/helpers/SubsurfaceTree.cpp | 3 +++ 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/Window.cpp b/src/Window.cpp index 01b58253..73835ccd 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -318,7 +318,7 @@ void CWindow::destroyToplevelHandle() { } void CWindow::updateToplevel() { - updateSurfaceOutputs(); + updateSurfaceScaleTransformDetails(); if (!m_phForeignToplevel) return; @@ -345,8 +345,8 @@ void sendLeaveIter(wlr_surface* pSurface, int x, int y, void* data) { wlr_surface_send_leave(pSurface, OUTPUT); } -void CWindow::updateSurfaceOutputs() { - if (m_iLastSurfaceMonitorID == m_iMonitorID || !m_bIsMapped || m_bHidden) +void CWindow::updateSurfaceScaleTransformDetails() { + if (!m_bIsMapped || m_bHidden) return; const auto PLASTMONITOR = g_pCompositor->getMonitorFromID(m_iLastSurfaceMonitorID); @@ -355,10 +355,12 @@ void CWindow::updateSurfaceOutputs() { const auto PNEWMONITOR = g_pCompositor->getMonitorFromID(m_iMonitorID); - if (PLASTMONITOR && PLASTMONITOR->m_bEnabled) - wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendLeaveIter, PLASTMONITOR->output); + if (PNEWMONITOR != PLASTMONITOR) { + if (PLASTMONITOR && PLASTMONITOR->m_bEnabled) + wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendLeaveIter, PLASTMONITOR->output); - wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendEnterIter, PNEWMONITOR->output); + wlr_surface_for_each_surface(m_pWLSurface.wlr(), sendEnterIter, PNEWMONITOR->output); + } wlr_surface_for_each_surface( m_pWLSurface.wlr(), diff --git a/src/Window.hpp b/src/Window.hpp index 559e4c90..d700af7e 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -356,7 +356,7 @@ class CWindow { void createToplevelHandle(); void destroyToplevelHandle(); void updateToplevel(); - void updateSurfaceOutputs(); + void updateSurfaceScaleTransformDetails(); void moveToWorkspace(int); CWindow* X11TransientFor(); void onUnmap(); diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp index 13f3f829..56f1d757 100644 --- a/src/events/Monitors.cpp +++ b/src/events/Monitors.cpp @@ -109,7 +109,7 @@ void Events::listener_newOutput(wl_listener* listener, void* data) { for (auto& w : g_pCompositor->m_vWindows) { if (w->m_iMonitorID == PNEWMONITOR->ID) { w->m_iLastSurfaceMonitorID = -1; - w->updateSurfaceOutputs(); + w->updateSurfaceScaleTransformDetails(); } } } diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index ce5103ee..b3c811c1 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -803,7 +803,7 @@ void Events::listener_commitWindow(void* owner, void* data) { PWINDOW->m_pPendingSizeAck.reset(); } - PWINDOW->updateSurfaceOutputs(); + PWINDOW->updateSurfaceScaleTransformDetails(); g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 3b4f4016..2f23c0d7 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -621,7 +621,7 @@ void CMonitor::setSpecialWorkspace(CWorkspace* const pWorkspace) { for (auto& w : g_pCompositor->m_vWindows) { if (w->m_iWorkspaceID == pWorkspace->m_iID) { w->m_iMonitorID = ID; - w->updateSurfaceOutputs(); + w->updateSurfaceScaleTransformDetails(); const auto MIDDLE = w->middle(); if (w->m_bIsFloating && !VECINRECT(MIDDLE, vecPosition.x, vecPosition.y, vecPosition.x + vecSize.x, vecPosition.y + vecSize.y) && w->m_iX11Type != 2) { diff --git a/src/helpers/SubsurfaceTree.cpp b/src/helpers/SubsurfaceTree.cpp index 5891411b..41b968e4 100644 --- a/src/helpers/SubsurfaceTree.cpp +++ b/src/helpers/SubsurfaceTree.cpp @@ -178,6 +178,9 @@ void Events::listener_mapSubsurface(void* owner, void* data) { Debug::log(LOG, "Subsurface {:x} mapped", (uintptr_t)subsurface->pSubsurface); subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface, subsurface->pWindowOwner); + + if (subsurface->pWindowOwner) + subsurface->pWindowOwner->updateSurfaceScaleTransformDetails(); } void Events::listener_unmapSubsurface(void* owner, void* data) { From b240704bee1d04eacc27654ea875cf6f15033c7c Mon Sep 17 00:00:00 2001 From: vaxerski Date: Tue, 9 Jan 2024 20:42:07 +0100 Subject: [PATCH 502/513] renderer: allow rendering multiple fullscreen windows in third fs pass something might be fading out, sliding out, etc. We handle it before, why not use it? fixes #4076 --- src/render/Renderer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 22613b4f..b7776ee6 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -290,11 +290,14 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(CMonitor* pMonitor, CWorksp continue; } - if (w->m_iWorkspaceID != pMonitor->activeWorkspace || !w->m_bIsFullscreen) + if (!w->m_bIsFullscreen) continue; renderWindow(w.get(), pMonitor, time, pWorkspace->m_efFullscreenMode != FULLSCREEN_FULL, RENDER_PASS_ALL); + if (w->m_iWorkspaceID != pWorkspace->m_iID) + continue; + pWorkspaceWindow = w.get(); } From d484506600e8e1065bef8df0ec0ed61393601a4d Mon Sep 17 00:00:00 2001 From: vaxerski Date: Wed, 10 Jan 2024 18:06:38 +0100 Subject: [PATCH 503/513] keybinds: fix tracking of sent key states --- src/managers/KeybindManager.cpp | 45 ++++++++++++++++++--------------- src/managers/KeybindManager.hpp | 1 + 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 21cc1f74..6a7366e3 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -313,9 +313,10 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard .keysym = keysym, .keycode = KEYCODE, .modmaskAtPressTime = MODS, + .sent = true, }; - bool found = false; + bool suppressEvent = false; if (e->state == WL_KEYBOARD_KEY_STATE_PRESSED) { // clean repeat if (m_pActiveKeybindEventSource) { @@ -326,10 +327,12 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard m_dPressedKeys.push_back(KEY); - found = handleKeybinds(MODS, KEY, true); + suppressEvent = handleKeybinds(MODS, KEY, true); - if (found) + if (suppressEvent) shadowKeybinds(keysym, KEYCODE); + + m_dPressedKeys.back().sent = !suppressEvent; } else { // key release // clean repeat if (m_pActiveKeybindEventSource) { @@ -341,11 +344,11 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard bool foundInPressedKeys = false; for (auto it = m_dPressedKeys.begin(); it != m_dPressedKeys.end();) { if (it->keycode == KEYCODE) { - if (!foundInPressedKeys) { - found = handleKeybinds(MODS, *it, false); - foundInPressedKeys = true; - } - it = m_dPressedKeys.erase(it); + suppressEvent = handleKeybinds(MODS, *it, false); + foundInPressedKeys = true; + suppressEvent = !it->sent; + it = m_dPressedKeys.erase(it); + break; } else { ++it; } @@ -353,13 +356,13 @@ bool CKeybindManager::onKeyEvent(wlr_keyboard_key_event* e, SKeyboard* pKeyboard if (!foundInPressedKeys) { Debug::log(ERR, "BUG THIS: key not found in m_dPressedKeys"); // fallback with wrong `KEY.modmaskAtPressTime`, this can be buggy - found = handleKeybinds(MODS, KEY, false); + suppressEvent = handleKeybinds(MODS, KEY, false); } shadowKeybinds(); } - return !found && !mouseBindWasActive; + return !suppressEvent && !mouseBindWasActive; } bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) { @@ -396,7 +399,7 @@ bool CKeybindManager::onAxisEvent(wlr_pointer_axis_event* e) { bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) { const auto MODS = g_pInputManager->accumulateModsFromAllKBs(); - bool found = false; + bool suppressEvent = false; m_uLastMouseCode = e->button; m_uLastCode = 0; @@ -414,19 +417,21 @@ bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) { if (e->state == WLR_BUTTON_PRESSED) { m_dPressedKeys.push_back(KEY); - found = handleKeybinds(MODS, KEY, true); + suppressEvent = handleKeybinds(MODS, KEY, true); - if (found) + if (suppressEvent) shadowKeybinds(); + + m_dPressedKeys.back().sent = !suppressEvent; } else { bool foundInPressedKeys = false; for (auto it = m_dPressedKeys.begin(); it != m_dPressedKeys.end();) { if (it->keyName == KEY_NAME) { - if (!foundInPressedKeys) { - found = handleKeybinds(MODS, *it, false); - foundInPressedKeys = true; - } - it = m_dPressedKeys.erase(it); + suppressEvent = handleKeybinds(MODS, *it, false); + foundInPressedKeys = true; + suppressEvent = !it->sent; + it = m_dPressedKeys.erase(it); + break; } else { ++it; } @@ -434,13 +439,13 @@ bool CKeybindManager::onMouseEvent(wlr_pointer_button_event* e) { if (!foundInPressedKeys) { Debug::log(ERR, "BUG THIS: key not found in m_dPressedKeys (2)"); // fallback with wrong `KEY.modmaskAtPressTime`, this can be buggy - found = handleKeybinds(MODS, KEY, false); + suppressEvent = handleKeybinds(MODS, KEY, false); } shadowKeybinds(); } - return !found && !mouseBindWasActive; + return !suppressEvent && !mouseBindWasActive; } void CKeybindManager::resizeWithBorder(wlr_pointer_button_event* e) { diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 631b0147..957cbdf6 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -41,6 +41,7 @@ struct SPressedKeyWithMods { xkb_keysym_t keysym = 0; uint32_t keycode = 0; uint32_t modmaskAtPressTime = 0; + bool sent = false; }; class CKeybindManager { From 8d31c84483be7cc6f909d73c6ecd4c0b4bdc3360 Mon Sep 17 00:00:00 2001 From: Clyybber Date: Wed, 10 Jan 2024 18:08:58 +0100 Subject: [PATCH 504/513] layout: Round window pos and size on togglefloating (#4407) Also restore the behaviour introduced in bc4a51dbbb285391c9ed45b1b6ca7c2037b7ba71 --- src/layout/IHyprLayout.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 6a03ac80..2a8fdf53 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -469,16 +469,18 @@ void IHyprLayout::changeWindowFloatingMode(CWindow* pWindow) { g_pCompositor->changeWindowZOrder(pWindow, true); + CBox wb = {pWindow->m_vRealPosition.goalv() + (pWindow->m_vRealSize.goalv() - pWindow->m_vLastFloatingSize) / 2.f, pWindow->m_vLastFloatingSize}; + wb.round(); + if (DELTALESSTHAN(pWindow->m_vRealSize.vec().x, pWindow->m_vLastFloatingSize.x, 10) && DELTALESSTHAN(pWindow->m_vRealSize.vec().y, pWindow->m_vLastFloatingSize.y, 10)) { - pWindow->m_vRealPosition = pWindow->m_vRealPosition.goalv() + (pWindow->m_vRealSize.goalv() - pWindow->m_vLastFloatingSize) / 2.f + Vector2D{10, 10}; - pWindow->m_vRealSize = pWindow->m_vLastFloatingSize - Vector2D{20, 20}; + wb = {wb.pos() + Vector2D{10, 10}, wb.size() - Vector2D{20, 20}}; } - pWindow->m_vRealPosition = pWindow->m_vRealPosition.goalv() + (pWindow->m_vRealSize.goalv() - pWindow->m_vLastFloatingSize) / 2.f; - pWindow->m_vRealSize = pWindow->m_vLastFloatingSize; + pWindow->m_vRealPosition = wb.pos(); + pWindow->m_vRealSize = wb.size(); - pWindow->m_vSize = pWindow->m_vRealSize.goalv(); - pWindow->m_vPosition = pWindow->m_vRealPosition.goalv(); + pWindow->m_vSize = wb.pos(); + pWindow->m_vPosition = wb.size(); g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID)); From 6b92144f15117f9f7d93fe9867d6ec849d9abce1 Mon Sep 17 00:00:00 2001 From: vaxerski Date: Thu, 11 Jan 2024 13:15:20 +0100 Subject: [PATCH 505/513] surface: avoid spam of window surfaces with scale and transform events fixes #4408 --- src/Compositor.cpp | 17 +++++++++++++++++ src/Window.cpp | 7 ++++++- src/events/Windows.cpp | 2 -- src/helpers/WLSurface.hpp | 8 +++++++- src/render/OpenGL.cpp | 4 +++- src/render/Renderer.cpp | 9 +++++++-- 6 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 62903cf9..cbdcd6b8 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2797,10 +2797,27 @@ void CCompositor::leaveUnsafeState() { void CCompositor::setPreferredScaleForSurface(wlr_surface* pSurface, double scale) { g_pProtocolManager->m_pFractionalScaleProtocolManager->setPreferredScaleForSurface(pSurface, scale); wlr_surface_set_preferred_buffer_scale(pSurface, static_cast(std::ceil(scale))); + + const auto PSURFACE = CWLSurface::surfaceFromWlr(pSurface); + if (!PSURFACE) { + Debug::log(WARN, "Orphaned wlr_surface {:x} in setPreferredScaleForSurface", (uintptr_t)pSurface); + return; + } + + PSURFACE->m_fLastScale = scale; + PSURFACE->m_iLastScale = static_cast(std::ceil(scale)); } void CCompositor::setPreferredTransformForSurface(wlr_surface* pSurface, wl_output_transform transform) { wlr_surface_set_preferred_buffer_transform(pSurface, transform); + + const auto PSURFACE = CWLSurface::surfaceFromWlr(pSurface); + if (!PSURFACE) { + Debug::log(WARN, "Orphaned wlr_surface {:x} in setPreferredTransformForSurface", (uintptr_t)pSurface); + return; + } + + PSURFACE->m_eLastTransform = transform; } void CCompositor::updateSuspendedStates() { diff --git a/src/Window.cpp b/src/Window.cpp index 73835ccd..818b4089 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -366,7 +366,12 @@ void CWindow::updateSurfaceScaleTransformDetails() { m_pWLSurface.wlr(), [](wlr_surface* surf, int x, int y, void* data) { const auto PMONITOR = g_pCompositor->getMonitorFromID(((CWindow*)data)->m_iMonitorID); - g_pCompositor->setPreferredScaleForSurface(surf, PMONITOR ? PMONITOR->scale : 1.f); + + const auto PSURFACE = CWLSurface::surfaceFromWlr(surf); + if (PSURFACE && PSURFACE->m_fLastScale == PMONITOR->scale) + return; + + g_pCompositor->setPreferredScaleForSurface(surf, PMONITOR->scale); g_pCompositor->setPreferredTransformForSurface(surf, PMONITOR->transform); }, this); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index b3c811c1..cb7a6aaf 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -803,8 +803,6 @@ void Events::listener_commitWindow(void* owner, void* data) { PWINDOW->m_pPendingSizeAck.reset(); } - PWINDOW->updateSurfaceScaleTransformDetails(); - g_pHyprRenderer->damageSurface(PWINDOW->m_pWLSurface.wlr(), PWINDOW->m_vRealPosition.goalv().x, PWINDOW->m_vRealPosition.goalv().y, PWINDOW->m_bIsX11 ? 1.0 / PWINDOW->m_fX11SurfaceScaledBy : 1.0); diff --git a/src/helpers/WLSurface.hpp b/src/helpers/WLSurface.hpp index faef4353..03714bbf 100644 --- a/src/helpers/WLSurface.hpp +++ b/src/helpers/WLSurface.hpp @@ -28,8 +28,14 @@ class CWLSurface { bool m_bFillIgnoreSmall = false; // if present, means this is a base surface of a window. Cleaned on unassign() - CWindow* m_pOwner = nullptr; + 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; diff --git a/src/render/OpenGL.cpp b/src/render/OpenGL.cpp index 2dd4ca0e..55a48a46 100644 --- a/src/render/OpenGL.cpp +++ b/src/render/OpenGL.cpp @@ -2019,8 +2019,10 @@ void CHyprOpenGLImpl::clearWithTex() { TEXIT = m_mMonitorBGTextures.find(m_RenderData.pMonitor); } + CBox box = {0, 0, m_RenderData.pMonitor->vecPixelSize.x, m_RenderData.pMonitor->vecPixelSize.y}; + if (TEXIT != m_mMonitorBGTextures.end()) - renderTexturePrimitive(TEXIT->second, &m_mMonitorRenderResources[m_RenderData.pMonitor].backgroundTexBox); + renderTexture(TEXIT->second, &box, 1); } void CHyprOpenGLImpl::destroyMonitorResources(CMonitor* pMonitor) { diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index b7776ee6..6d5af8d9 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -1997,6 +1997,7 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR Vector2D logicalZero = pMonitor->vecPixelSize / scaleZero; if (logicalZero == logicalZero.round()) { pMonitor->scale = scaleZero; + wlr_output_set_scale(pMonitor->output, pMonitor->scale); } else { for (size_t i = 1; i < 90; ++i) { double scaleUp = (searchScale + i) / 120.0; @@ -2034,11 +2035,15 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR } else pMonitor->scale = searchScale; } + + // for wlroots, that likes flooring, we have to do this. + double logicalX = std::round(pMonitor->vecPixelSize.x / pMonitor->scale); + logicalX += 0.1; + + wlr_output_set_scale(pMonitor->output, pMonitor->vecPixelSize.x / logicalX); } } - wlr_output_set_scale(pMonitor->output, pMonitor->scale); - // clang-format off static const std::array>, 2> formats{ std::vector>{ /* 10-bit */ From babb9c07b045e21b5549cdcc3096d677e9db35b3 Mon Sep 17 00:00:00 2001 From: scorpion-26 Date: Thu, 11 Jan 2024 19:22:40 +0100 Subject: [PATCH 506/513] swipe: Prevent hiding current workspace when swiping (#4417) When workspace_swipe_use_r is enabled, swiping from WS 1 to a non-empty WS 2 would hide WS 1 (Similar effect to issue #4076). This is caused by a faulty check which doesn't consider, that workspaceIDLeft could be the current workspace. This bug is only a problem for r, because m wraps around on WS 1 m-1, whereas r stays on WS 1. --- src/managers/input/Swipe.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/managers/input/Swipe.cpp b/src/managers/input/Swipe.cpp index f345e4f5..38ec8aa2 100644 --- a/src/managers/input/Swipe.cpp +++ b/src/managers/input/Swipe.cpp @@ -265,7 +265,7 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { PWORKSPACE->m_bForceRendering = true; PWORKSPACE->m_fAlpha.setValueAndWarp(1.f); - if (workspaceIDLeft != workspaceIDRight) { + if (workspaceIDLeft != workspaceIDRight && workspaceIDRight != m_sActiveSwipe.pWorkspaceBegin->m_iID) { const auto PWORKSPACER = g_pCompositor->getWorkspaceByID(workspaceIDRight); if (PWORKSPACER) { @@ -305,7 +305,7 @@ void CInputManager::onSwipeUpdate(wlr_pointer_swipe_update_event* e) { PWORKSPACE->m_bForceRendering = true; PWORKSPACE->m_fAlpha.setValueAndWarp(1.f); - if (workspaceIDLeft != workspaceIDRight) { + if (workspaceIDLeft != workspaceIDRight && workspaceIDLeft != m_sActiveSwipe.pWorkspaceBegin->m_iID) { const auto PWORKSPACEL = g_pCompositor->getWorkspaceByID(workspaceIDLeft); if (PWORKSPACEL) { From c4da4b026deefd58f532353b64e9f17130e760ca Mon Sep 17 00:00:00 2001 From: Zach DeCook Date: Fri, 12 Jan 2024 09:43:16 -0500 Subject: [PATCH 507/513] layershell: Fix greedy mouse grab from keyboard_interactive layer (#4401) * Layer: Don't allow a keyboard-layer to steal focus from other layers * Input: Don't change keyboard focus on click if focus is locked --- src/Compositor.cpp | 8 -------- src/managers/input/InputManager.cpp | 4 ++-- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index cbdcd6b8..2b3fc7d3 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1102,14 +1102,6 @@ wlr_surface* CCompositor::vectorToLayerSurface(const Vector2D& pos, std::vector< auto SURFACEAT = wlr_layer_surface_v1_surface_at(ls->layerSurface, pos.x - ls->geometry.x, pos.y - ls->geometry.y, &sCoords->x, &sCoords->y); - if (ls->layerSurface->current.keyboard_interactive && ls->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { - if (!SURFACEAT) - SURFACEAT = ls->layerSurface->surface; - - *ppLayerSurfaceFound = ls.get(); - return SURFACEAT; - } - if (SURFACEAT) { if (!pixman_region32_not_empty(&SURFACEAT->input_region)) continue; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 207df738..8bfdb65c 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -359,7 +359,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { bool allowKeyboardRefocus = true; - if (!refocus && g_pCompositor->m_pLastFocus) { + if (g_pCompositor->m_pLastFocus) { const auto PLS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus); if (PLS && PLS->layerSurface->current.keyboard_interactive == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) @@ -421,7 +421,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) { m_bLastFocusOnLS = false; return; // don't enter any new surfaces } else { - if (((FOLLOWMOUSE != 3 && allowKeyboardRefocus) && (*PMOUSEREFOCUS || m_pLastMouseFocus != pFoundWindow)) || refocus) { + if (allowKeyboardRefocus && ((FOLLOWMOUSE != 3 && (*PMOUSEREFOCUS || m_pLastMouseFocus != pFoundWindow)) || refocus)) { m_pLastMouseFocus = pFoundWindow; g_pCompositor->focusWindow(pFoundWindow, foundSurface); } From 4cee94b91c9337036f3ea94f80cf8259c5c51cb4 Mon Sep 17 00:00:00 2001 From: 1over137 <22680475+1over137@users.noreply.github.com> Date: Sun, 14 Jan 2024 13:56:35 +0000 Subject: [PATCH 508/513] fractional: Set preferred scale on monitor config reload (#4406) --- src/render/Renderer.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 6d5af8d9..cf246c7c 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -2101,6 +2101,13 @@ bool CHyprRenderer::applyMonitorRule(CMonitor* pMonitor, SMonitorRule* pMonitorR wlr_damage_ring_set_bounds(&pMonitor->damage, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y); + // Set scale for all surfaces on this monitor, needed for some clients + // but not on unsafe state to avoid crashes + if (!g_pCompositor->m_bUnsafeState) { + for (auto& w : g_pCompositor->m_vWindows) { + w->updateSurfaceScaleTransformDetails(); + } + } // updato us arrangeLayersForMonitor(pMonitor->ID); From 13d9a637d61ffdd0cb23dda80f6a971f17e0f5b3 Mon Sep 17 00:00:00 2001 From: dranull <150595692+dranull@users.noreply.github.com> Date: Sun, 14 Jan 2024 17:12:52 +0000 Subject: [PATCH 509/513] hyprctl: screen_shader config fixes (#4102) * Allow "/" in values of requests * Don't tick on empty value --- src/config/ConfigManager.cpp | 2 +- src/debug/HyprCtl.cpp | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 69128c52..57985c41 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -550,7 +550,7 @@ void CConfigManager::configSetValueSafe(const std::string& COMMAND, const std::s } } - if (COMMAND == "decoration:screen_shader") { + if (COMMAND == "decoration:screen_shader" && VALUE != STRVAL_EMPTY) { const auto PATH = absolutePath(VALUE, configCurrentPath); configPaths.push_back(PATH); diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 78d20903..490f14c9 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1402,13 +1402,20 @@ std::string getReply(std::string request) { auto format = HyprCtl::FORMAT_NORMAL; // process flags for non-batch requests - if (!request.contains("[[BATCH]]") && request.contains("/")) { + if (!request.starts_with("[[BATCH]]") && request.contains("/")) { long unsigned int sepIndex = 0; for (const auto& c : request) { if (c == '/') { // stop at separator break; } + // after whitespace assume the first word as a keyword, + // so its value can have slashes (e.g., a path) + if (c == ' ') { + sepIndex = request.size(); + break; + } + sepIndex++; if (c == 'j') From b6516bad0281efb55195e8db180aa2dcaf8b98e4 Mon Sep 17 00:00:00 2001 From: Isaac Myhal Date: Sun, 14 Jan 2024 12:27:32 -0500 Subject: [PATCH 510/513] config: Add border gradients to windowrulev2 (#4335) * Add border gradients to windowrulev2 * windowrule border gradient: Use CVarList to parse * windowrule border gradient: No {} around short ifs --- src/Compositor.cpp | 10 +++---- src/Window.cpp | 46 ++++++++++++++++++++++++++------- src/Window.hpp | 12 ++++----- src/config/ConfigDataValues.hpp | 1 + src/debug/HyprCtl.cpp | 4 +-- 5 files changed, 50 insertions(+), 23 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 2b3fc7d3..b37e25b2 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -1884,15 +1884,13 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) { if (pWindow == m_pLastWindow) { const auto* const ACTIVECOLOR = !pWindow->m_sGroupData.pNextWindow ? (!pWindow->m_sGroupData.deny ? ACTIVECOL : NOGROUPACTIVECOL) : (GROUPLOCKED ? GROUPACTIVELOCKEDCOL : GROUPACTIVECOL); - setBorderColor(pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying() >= 0 ? - CGradientValueData(CColor(pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying())) : - *ACTIVECOLOR); + setBorderColor(pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying().m_vColors.empty() ? *ACTIVECOLOR : + pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying()); } else { const auto* const INACTIVECOLOR = !pWindow->m_sGroupData.pNextWindow ? (!pWindow->m_sGroupData.deny ? INACTIVECOL : NOGROUPINACTIVECOL) : (GROUPLOCKED ? GROUPINACTIVELOCKEDCOL : GROUPINACTIVECOL); - setBorderColor(pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying() >= 0 ? - CGradientValueData(CColor(pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying())) : - *INACTIVECOLOR); + setBorderColor(pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying().m_vColors.empty() ? *INACTIVECOLOR : + pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying()); } } diff --git a/src/Window.cpp b/src/Window.cpp index 818b4089..5a50713b 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -614,14 +614,42 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { m_sAdditionalConfigData.animationStyle = STYLE; } else if (r.szRule.starts_with("bordercolor")) { try { - std::string colorPart = removeBeginEndSpacesTabs(r.szRule.substr(r.szRule.find_first_of(' ') + 1)); + // Each vector will only get used if it has at least one color + CGradientValueData activeBorderGradient = {}; + CGradientValueData inactiveBorderGradient = {}; + bool active = true; + CVarList colorsAndAngles = CVarList(removeBeginEndSpacesTabs(r.szRule.substr(r.szRule.find_first_of(' ') + 1)), 0, 's', true); - if (colorPart.contains(' ')) { - // we have a space, 2 values - m_sSpecialRenderData.activeBorderColor = configStringToInt(colorPart.substr(0, colorPart.find_first_of(' '))); - m_sSpecialRenderData.inactiveBorderColor = configStringToInt(colorPart.substr(colorPart.find_first_of(' ') + 1)); - } else { - m_sSpecialRenderData.activeBorderColor = configStringToInt(colorPart); + // Basic form has only two colors, everything else can be parsed as a gradient + if (colorsAndAngles.size() == 2 && !colorsAndAngles[1].contains("deg")) { + m_sSpecialRenderData.activeBorderColor = CGradientValueData(CColor(configStringToInt(colorsAndAngles[0]))); + m_sSpecialRenderData.inactiveBorderColor = CGradientValueData(CColor(configStringToInt(colorsAndAngles[1]))); + 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()) + m_sSpecialRenderData.activeBorderColor = activeBorderGradient; + else { + m_sSpecialRenderData.activeBorderColor = activeBorderGradient; + m_sSpecialRenderData.inactiveBorderColor = inactiveBorderGradient; } } catch (std::exception& e) { Debug::log(ERR, "BorderColor rule \"{}\" failed with: {}", r.szRule, e.what()); } } else if (r.szRule == "dimaround") { @@ -651,8 +679,8 @@ void CWindow::applyDynamicRule(const SWindowRule& r) { } void CWindow::updateDynamicRules() { - m_sSpecialRenderData.activeBorderColor = -1; - m_sSpecialRenderData.inactiveBorderColor = -1; + m_sSpecialRenderData.activeBorderColor = CGradientValueData(); + m_sSpecialRenderData.inactiveBorderColor = CGradientValueData(); m_sSpecialRenderData.alpha = 1.f; m_sSpecialRenderData.alphaInactive = -1.f; m_sAdditionalConfigData.forceNoBlur = false; diff --git a/src/Window.hpp b/src/Window.hpp index d700af7e..bbe7dc07 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -106,13 +106,13 @@ class CWindowOverridableVar { }; struct SWindowSpecialRenderData { - CWindowOverridableVar alphaOverride = false; - CWindowOverridableVar alpha = 1.f; - CWindowOverridableVar alphaInactiveOverride = false; - CWindowOverridableVar alphaInactive = -1.f; // -1 means unset + CWindowOverridableVar alphaOverride = false; + CWindowOverridableVar alpha = 1.f; + CWindowOverridableVar alphaInactiveOverride = false; + CWindowOverridableVar alphaInactive = -1.f; // -1 means unset - CWindowOverridableVar activeBorderColor = -1; // -1 means unset - CWindowOverridableVar inactiveBorderColor = -1; // -1 means unset + CWindowOverridableVar activeBorderColor = CGradientValueData(); // empty color vector means unset + CWindowOverridableVar inactiveBorderColor = CGradientValueData(); // empty color vector means unset // set by the layout CWindowOverridableVar borderSize = -1; // -1 means unset diff --git a/src/config/ConfigDataValues.hpp b/src/config/ConfigDataValues.hpp index f6bf9881..14b5e51d 100644 --- a/src/config/ConfigDataValues.hpp +++ b/src/config/ConfigDataValues.hpp @@ -16,6 +16,7 @@ class ICustomConfigValueData { class CGradientValueData : public ICustomConfigValueData { public: + CGradientValueData(){}; CGradientValueData(CColor col) { m_vColors.push_back(col); }; diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 490f14c9..79855d27 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -1138,9 +1138,9 @@ std::string dispatchSetProp(std::string request) { } else if (PROP == "alphainactive") { PWINDOW->m_sSpecialRenderData.alphaInactive.forceSetIgnoreLocked(std::stof(VAL), lock); } else if (PROP == "activebordercolor") { - PWINDOW->m_sSpecialRenderData.activeBorderColor.forceSetIgnoreLocked(configStringToInt(VAL), lock); + PWINDOW->m_sSpecialRenderData.activeBorderColor.forceSetIgnoreLocked(CGradientValueData(CColor(configStringToInt(VAL))), lock); } else if (PROP == "inactivebordercolor") { - PWINDOW->m_sSpecialRenderData.inactiveBorderColor.forceSetIgnoreLocked(configStringToInt(VAL), lock); + PWINDOW->m_sSpecialRenderData.inactiveBorderColor.forceSetIgnoreLocked(CGradientValueData(CColor(configStringToInt(VAL))), lock); } else if (PROP == "forcergbx") { PWINDOW->m_sAdditionalConfigData.forceRGBX.forceSetIgnoreLocked(configStringToInt(VAL), lock); } else if (PROP == "bordersize") { From dcd7a92b01a360bbe7afa7299604c4040abb4c62 Mon Sep 17 00:00:00 2001 From: fufexan Date: Mon, 15 Jan 2024 00:03:29 +0000 Subject: [PATCH 511/513] [gha] Nix: update inputs --- flake.lock | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/flake.lock b/flake.lock index 1619129f..d7db1bca 100644 --- a/flake.lock +++ b/flake.lock @@ -25,7 +25,10 @@ }, "hyprlang": { "inputs": { - "nixpkgs": "nixpkgs_2" + "nixpkgs": [ + "xdph", + "nixpkgs" + ] }, "locked": { "lastModified": 1704287638, @@ -43,27 +46,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1704194953, - "narHash": "sha256-RtDKd8Mynhe5CFnVT8s0/0yqtWFMM9LmCzXv/YKxnq4=", + "lastModified": 1705133751, + "narHash": "sha256-rCIsyE80jgiOU78gCWN3A0wE0tR2GI5nH6MlS+HaaSQ=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "bd645e8668ec6612439a9ee7e71f7eac4099d4f6", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1702645756, - "narHash": "sha256-qKI6OR3TYJYQB3Q8mAZ+DG4o/BR9ptcv9UnRV2hzljc=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "40c3c94c241286dd2243ea34d3aef8a488f9e4d0", + "rev": "9b19f5e77dd906cb52dade0b7bd280339d2a1f3d", "type": "github" }, "original": { @@ -130,11 +117,11 @@ ] }, "locked": { - "lastModified": 1704400467, - "narHash": "sha256-IsEAKBCorRlN53FwFAMbyGLRsPVu/ZrWEJtCwykPds8=", + "lastModified": 1704659450, + "narHash": "sha256-3lyoUVtUWz1LuxbltAtkJSK2IlVXmKhxCRU2/0PYCms=", "owner": "hyprwm", "repo": "xdg-desktop-portal-hyprland", - "rev": "1c802128f6cc3db29a8ef01552b1a22f894eeefd", + "rev": "6a5de92769d5b7038134044053f90e7458f6a197", "type": "github" }, "original": { From f14c5ea5c56858260c1133d8003fc5961ace373d Mon Sep 17 00:00:00 2001 From: MightyPlaza <123664421+MightyPlaza@users.noreply.github.com> Date: Mon, 15 Jan 2024 15:17:42 +0000 Subject: [PATCH 512/513] groupbar: separate gradients from title (#4444) * separate gradients from title logic modified: src/config/ConfigManager.cpp modified: src/render/decorations/CHyprGroupBarDecoration.cpp * fix disabled extents modified: src/render/decorations/CHyprGroupBarDecoration.cpp * fix disabled height modified: src/render/decorations/CHyprGroupBarDecoration.cpp --- src/config/ConfigManager.cpp | 1 + .../decorations/CHyprGroupBarDecoration.cpp | 34 ++++++++++--------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 57985c41..402d879e 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -138,6 +138,7 @@ void CConfigManager::setDefaultVars() { configValues["group:groupbar:font_family"].strValue = "Sans"; configValues["group:groupbar:font_size"].intValue = 8; configValues["group:groupbar:gradients"].intValue = 1; + configValues["group:groupbar:height"].intValue = 14; configValues["group:groupbar:priority"].intValue = 3; configValues["group:groupbar:render_titles"].intValue = 1; configValues["group:groupbar:scrolling"].intValue = 1; diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 4569337a..9a74dcd7 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -26,9 +26,10 @@ CHyprGroupBarDecoration::CHyprGroupBarDecoration(CWindow* pWindow) : IHyprWindow CHyprGroupBarDecoration::~CHyprGroupBarDecoration() {} SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() { - static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("group:groupbar:render_titles")->intValue; - static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue; - static auto* const PENABLED = &g_pConfigManager->getConfigValuePtr("group:groupbar:enabled")->intValue; + static auto* const PHEIGHT = &g_pConfigManager->getConfigValuePtr("group:groupbar:height")->intValue; + static auto* const PENABLED = &g_pConfigManager->getConfigValuePtr("group:groupbar:enabled")->intValue; + static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("group:groupbar:render_titles")->intValue; + static auto* const PGRADIENTS = &g_pConfigManager->getConfigValuePtr("group:groupbar:gradients")->intValue; SDecorationPositioningInfo info; info.policy = DECORATION_POSITION_STICKY; @@ -37,7 +38,7 @@ SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() { info.reserved = true; if (*PENABLED && m_pWindow->m_sSpecialRenderData.decorate) - info.desiredExtents = {{0, BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0) + 2}, {0, 0}}; + info.desiredExtents = {{0, BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0) + 2}, {0, 0}}; else info.desiredExtents = {{0, 0}, {0, 0}}; @@ -90,6 +91,7 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& static auto* const PENABLED = &g_pConfigManager->getConfigValuePtr("group:groupbar:enabled")->intValue; static auto* const PRENDERTITLES = &g_pConfigManager->getConfigValuePtr("group:groupbar:render_titles")->intValue; static auto* const PTITLEFONTSIZE = &g_pConfigManager->getConfigValuePtr("group:groupbar:font_size")->intValue; + static auto* const PHEIGHT = &g_pConfigManager->getConfigValuePtr("group:groupbar:height")->intValue; static auto* const PGRADIENTS = &g_pConfigManager->getConfigValuePtr("group:groupbar:gradients")->intValue; if (!*PENABLED || !m_pWindow->m_sSpecialRenderData.decorate) @@ -99,7 +101,7 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& m_fBarWidth = (ASSIGNEDBOX.w - BAR_HORIZONTAL_PADDING * (barsToDraw - 1)) / barsToDraw; - const auto DESIREDHEIGHT = BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PRENDERTITLES ? *PTITLEFONTSIZE : 0) + 2; + const auto DESIREDHEIGHT = BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0) + 2; if (DESIREDHEIGHT != ASSIGNEDBOX.h) g_pDecorationPositioner->repositionDeco(this); @@ -128,12 +130,18 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& color.a *= a; g_pHyprOpenGL->renderRect(&rect, color); - // render title if necessary - if (*PRENDERTITLES) { - CBox rect = {ASSIGNEDBOX.x + xoff - pMonitor->vecPosition.x + offset.x, ASSIGNEDBOX.y - pMonitor->vecPosition.y + offset.y + BAR_PADDING_OUTER_VERT, m_fBarWidth, - ASSIGNEDBOX.h - BAR_INDICATOR_HEIGHT - BAR_PADDING_OUTER_VERT * 2}; - rect.scale(pMonitor->scale); + rect = {ASSIGNEDBOX.x + xoff - pMonitor->vecPosition.x + offset.x, ASSIGNEDBOX.y - pMonitor->vecPosition.y + offset.y + BAR_PADDING_OUTER_VERT, m_fBarWidth, + ASSIGNEDBOX.h - BAR_INDICATOR_HEIGHT - BAR_PADDING_OUTER_VERT * 2}; + rect.scale(pMonitor->scale); + if (*PGRADIENTS) { + const auto& GRADIENTTEX = (m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) : + (GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive)); + if (GRADIENTTEX.m_iTexID != 0) + g_pHyprOpenGL->renderTexture(GRADIENTTEX, &rect, 1.0); + } + + if (*PRENDERTITLES) { CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[i]->m_szTitle); if (!pTitleTex) @@ -142,12 +150,6 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D& Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale})) .get(); - const auto& GRADIENTTEX = (m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) : - (GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive)); - - if (*PGRADIENTS && GRADIENTTEX.m_iTexID != 0) - g_pHyprOpenGL->renderTexture(GRADIENTTEX, &rect, 1.0); - rect.y += (ASSIGNEDBOX.h / 2.0 - (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) / 2.0) * pMonitor->scale; rect.height = (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale; From 3c964a9fdc220250a85b1c498e5b6fad9390272f Mon Sep 17 00:00:00 2001 From: virchau13 Date: Mon, 15 Jan 2024 23:30:46 +0800 Subject: [PATCH 513/513] keybinds: Add dispatcher for xmonad/qtile-style workspace switching (#4439) * feat: implement xmonad/qtile-style workspace switching Implements the focusWorkspaceOnCurrentMonitor dispatcher and function, which implements XMonad/Qtile-style workspace switching. When called, focusWorkspaceOnCurrentMonitor will: 1. Send the requested workspace to the current monitor, 2. If the workspace was previously active on a different monitor, replace it with the workspace that was previously active on the current monitor, 3. Focus the workspace on the current monitor. * fix: address PR comments --- src/Compositor.cpp | 5 +- src/Compositor.hpp | 2 +- src/helpers/Monitor.cpp | 4 +- src/helpers/Monitor.hpp | 2 +- src/managers/KeybindManager.cpp | 159 ++++++++++++++++++++------------ src/managers/KeybindManager.hpp | 1 + 6 files changed, 109 insertions(+), 64 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index b37e25b2..8d16f22d 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -2114,7 +2114,7 @@ CMonitor* CCompositor::getMonitorFromString(const std::string& name) { return nullptr; } -void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMonitor) { +void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMonitor, bool noWarpCursor) { // We trust the workspace and monitor to be correct. @@ -2200,7 +2200,8 @@ void CCompositor::moveWorkspaceToMonitor(CWorkspace* pWorkspace, CMonitor* pMoni pWorkspace->startAnim(true, true, true); - wlr_cursor_warp(m_sWLRCursor, nullptr, pMonitor->vecPosition.x + pMonitor->vecTransformedSize.x / 2, pMonitor->vecPosition.y + pMonitor->vecTransformedSize.y / 2); + if (!noWarpCursor) + wlr_cursor_warp(m_sWLRCursor, nullptr, pMonitor->vecPosition.x + pMonitor->vecTransformedSize.x / 2, pMonitor->vecPosition.y + pMonitor->vecTransformedSize.y / 2); g_pInputManager->sendMotionEventsToFocused(); } diff --git a/src/Compositor.hpp b/src/Compositor.hpp index f954526c..22b94dbb 100644 --- a/src/Compositor.hpp +++ b/src/Compositor.hpp @@ -176,7 +176,7 @@ class CCompositor { void updateWorkspaceWindows(const int64_t& id); void updateWindowAnimatedDecorationValues(CWindow*); int getNextAvailableMonitorID(std::string const& name); - void moveWorkspaceToMonitor(CWorkspace*, CMonitor*); + void moveWorkspaceToMonitor(CWorkspace*, CMonitor*, bool noWarpCursor = false); void swapActiveWorkspaces(CMonitor*, CMonitor*); CMonitor* getMonitorFromString(const std::string&); bool workspaceIDOutOfBounds(const int64_t&); diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 2f23c0d7..e62d9d49 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -502,7 +502,7 @@ float CMonitor::getDefaultScale() { return 1; } -void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool noMouseMove) { +void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool noMouseMove, bool noFocus) { if (!pWorkspace) return; @@ -533,7 +533,7 @@ void CMonitor::changeWorkspace(CWorkspace* const pWorkspace, bool internal, bool } } - if (!g_pCompositor->m_pLastMonitor->specialWorkspaceID) { + if (!noFocus && !g_pCompositor->m_pLastMonitor->specialWorkspaceID) { static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; CWindow* pWindow = pWorkspace->getLastFocusedWindow(); diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index 2b196c96..943b929d 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -120,7 +120,7 @@ class CMonitor { void setMirror(const std::string&); bool isMirror(); float getDefaultScale(); - void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false); + void changeWorkspace(CWorkspace* const pWorkspace, bool internal = false, bool noMouseMove = false, bool noFocus = false); void changeWorkspace(const int& id, bool internal = false); void setSpecialWorkspace(CWorkspace* const pWorkspace); void setSpecialWorkspace(const int& id); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 6a7366e3..1fc8a679 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -19,64 +19,65 @@ CKeybindManager::CKeybindManager() { // initialize all dispatchers - m_mDispatchers["exec"] = spawn; - m_mDispatchers["execr"] = spawnRaw; - m_mDispatchers["killactive"] = killActive; - m_mDispatchers["closewindow"] = kill; - m_mDispatchers["togglefloating"] = toggleActiveFloating; - m_mDispatchers["workspace"] = changeworkspace; - m_mDispatchers["renameworkspace"] = renameWorkspace; - m_mDispatchers["fullscreen"] = fullscreenActive; - m_mDispatchers["fakefullscreen"] = fakeFullscreenActive; - m_mDispatchers["movetoworkspace"] = moveActiveToWorkspace; - m_mDispatchers["movetoworkspacesilent"] = moveActiveToWorkspaceSilent; - m_mDispatchers["pseudo"] = toggleActivePseudo; - m_mDispatchers["movefocus"] = moveFocusTo; - m_mDispatchers["movewindow"] = moveActiveTo; - m_mDispatchers["swapwindow"] = swapActive; - m_mDispatchers["centerwindow"] = centerWindow; - m_mDispatchers["togglegroup"] = toggleGroup; - m_mDispatchers["changegroupactive"] = changeGroupActive; - m_mDispatchers["movegroupwindow"] = moveGroupWindow; - m_mDispatchers["togglesplit"] = toggleSplit; - m_mDispatchers["splitratio"] = alterSplitRatio; - m_mDispatchers["focusmonitor"] = focusMonitor; - m_mDispatchers["movecursortocorner"] = moveCursorToCorner; - m_mDispatchers["movecursor"] = moveCursor; - m_mDispatchers["workspaceopt"] = workspaceOpt; - m_mDispatchers["exit"] = exitHyprland; - m_mDispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor; - m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor; - m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace; - m_mDispatchers["forcerendererreload"] = forceRendererReload; - m_mDispatchers["resizeactive"] = resizeActive; - m_mDispatchers["moveactive"] = moveActive; - m_mDispatchers["cyclenext"] = circleNext; - m_mDispatchers["focuswindowbyclass"] = focusWindow; - m_mDispatchers["focuswindow"] = focusWindow; - m_mDispatchers["submap"] = setSubmap; - m_mDispatchers["pass"] = pass; - m_mDispatchers["layoutmsg"] = layoutmsg; - m_mDispatchers["toggleopaque"] = toggleOpaque; - m_mDispatchers["dpms"] = dpms; - m_mDispatchers["movewindowpixel"] = moveWindow; - m_mDispatchers["resizewindowpixel"] = resizeWindow; - m_mDispatchers["swapnext"] = swapnext; - m_mDispatchers["swapactiveworkspaces"] = swapActiveWorkspaces; - m_mDispatchers["pin"] = pinActive; - m_mDispatchers["mouse"] = mouse; - m_mDispatchers["bringactivetotop"] = bringActiveToTop; - m_mDispatchers["alterzorder"] = alterZOrder; - m_mDispatchers["focusurgentorlast"] = focusUrgentOrLast; - m_mDispatchers["focuscurrentorlast"] = focusCurrentOrLast; - m_mDispatchers["lockgroups"] = lockGroups; - m_mDispatchers["lockactivegroup"] = lockActiveGroup; - m_mDispatchers["moveintogroup"] = moveIntoGroup; - m_mDispatchers["moveoutofgroup"] = moveOutOfGroup; - m_mDispatchers["movewindoworgroup"] = moveWindowOrGroup; - m_mDispatchers["setignoregrouplock"] = setIgnoreGroupLock; - m_mDispatchers["denywindowfromgroup"] = denyWindowFromGroup; - m_mDispatchers["global"] = global; + m_mDispatchers["exec"] = spawn; + m_mDispatchers["execr"] = spawnRaw; + m_mDispatchers["killactive"] = killActive; + m_mDispatchers["closewindow"] = kill; + m_mDispatchers["togglefloating"] = toggleActiveFloating; + m_mDispatchers["workspace"] = changeworkspace; + m_mDispatchers["renameworkspace"] = renameWorkspace; + m_mDispatchers["fullscreen"] = fullscreenActive; + m_mDispatchers["fakefullscreen"] = fakeFullscreenActive; + m_mDispatchers["movetoworkspace"] = moveActiveToWorkspace; + m_mDispatchers["movetoworkspacesilent"] = moveActiveToWorkspaceSilent; + m_mDispatchers["pseudo"] = toggleActivePseudo; + m_mDispatchers["movefocus"] = moveFocusTo; + m_mDispatchers["movewindow"] = moveActiveTo; + m_mDispatchers["swapwindow"] = swapActive; + m_mDispatchers["centerwindow"] = centerWindow; + m_mDispatchers["togglegroup"] = toggleGroup; + m_mDispatchers["changegroupactive"] = changeGroupActive; + m_mDispatchers["movegroupwindow"] = moveGroupWindow; + m_mDispatchers["togglesplit"] = toggleSplit; + m_mDispatchers["splitratio"] = alterSplitRatio; + m_mDispatchers["focusmonitor"] = focusMonitor; + m_mDispatchers["movecursortocorner"] = moveCursorToCorner; + m_mDispatchers["movecursor"] = moveCursor; + m_mDispatchers["workspaceopt"] = workspaceOpt; + m_mDispatchers["exit"] = exitHyprland; + m_mDispatchers["movecurrentworkspacetomonitor"] = moveCurrentWorkspaceToMonitor; + m_mDispatchers["focusworkspaceoncurrentmonitor"] = focusWorkspaceOnCurrentMonitor; + m_mDispatchers["moveworkspacetomonitor"] = moveWorkspaceToMonitor; + m_mDispatchers["togglespecialworkspace"] = toggleSpecialWorkspace; + m_mDispatchers["forcerendererreload"] = forceRendererReload; + m_mDispatchers["resizeactive"] = resizeActive; + m_mDispatchers["moveactive"] = moveActive; + m_mDispatchers["cyclenext"] = circleNext; + m_mDispatchers["focuswindowbyclass"] = focusWindow; + m_mDispatchers["focuswindow"] = focusWindow; + m_mDispatchers["submap"] = setSubmap; + m_mDispatchers["pass"] = pass; + m_mDispatchers["layoutmsg"] = layoutmsg; + m_mDispatchers["toggleopaque"] = toggleOpaque; + m_mDispatchers["dpms"] = dpms; + m_mDispatchers["movewindowpixel"] = moveWindow; + m_mDispatchers["resizewindowpixel"] = resizeWindow; + m_mDispatchers["swapnext"] = swapnext; + m_mDispatchers["swapactiveworkspaces"] = swapActiveWorkspaces; + m_mDispatchers["pin"] = pinActive; + m_mDispatchers["mouse"] = mouse; + m_mDispatchers["bringactivetotop"] = bringActiveToTop; + m_mDispatchers["alterzorder"] = alterZOrder; + m_mDispatchers["focusurgentorlast"] = focusUrgentOrLast; + m_mDispatchers["focuscurrentorlast"] = focusCurrentOrLast; + m_mDispatchers["lockgroups"] = lockGroups; + m_mDispatchers["lockactivegroup"] = lockActiveGroup; + m_mDispatchers["moveintogroup"] = moveIntoGroup; + m_mDispatchers["moveoutofgroup"] = moveOutOfGroup; + m_mDispatchers["movewindoworgroup"] = moveWindowOrGroup; + m_mDispatchers["setignoregrouplock"] = setIgnoreGroupLock; + m_mDispatchers["denywindowfromgroup"] = denyWindowFromGroup; + m_mDispatchers["global"] = global; m_tScrollTimer.reset(); @@ -1504,6 +1505,48 @@ void CKeybindManager::moveWorkspaceToMonitor(std::string args) { g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PMONITOR); } +void CKeybindManager::focusWorkspaceOnCurrentMonitor(std::string args) { + std::string workspaceName; + const int WORKSPACEID = getWorkspaceIDFromString(args, workspaceName); + + if (WORKSPACEID == WORKSPACE_INVALID) { + Debug::log(ERR, "focusWorkspaceOnCurrentMonitor invalid workspace!"); + return; + } + + const auto PCURRMONITOR = g_pCompositor->getMonitorFromCursor(); + + if (!PCURRMONITOR) { + Debug::log(ERR, "focusWorkspaceOnCurrentMonitor monitor doesn't exist!"); + return; + } + + auto PWORKSPACE = g_pCompositor->getWorkspaceByID(WORKSPACEID); + + if (!PWORKSPACE) { + PWORKSPACE = g_pCompositor->createNewWorkspace(WORKSPACEID, PCURRMONITOR->ID); + // we can skip the moving, since it's already on the current monitor + changeworkspace(PWORKSPACE->getConfigName()); + return; + } + + if (PWORKSPACE->m_iMonitorID != PCURRMONITOR->ID) { + const auto POLDMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); + if (!POLDMONITOR) { // wat + Debug::log(ERR, "focusWorkspaceOnCurrentMonitor old monitor doesn't exist!"); + return; + } + if (POLDMONITOR->activeWorkspace == WORKSPACEID) { + g_pCompositor->swapActiveWorkspaces(POLDMONITOR, PCURRMONITOR); + return; + } else { + g_pCompositor->moveWorkspaceToMonitor(PWORKSPACE, PCURRMONITOR, true); + } + } + + changeworkspace(PWORKSPACE->getConfigName()); +} + void CKeybindManager::toggleSpecialWorkspace(std::string args) { static auto* const PFOLLOWMOUSE = &g_pConfigManager->getConfigValuePtr("input:follow_mouse")->intValue; diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 957cbdf6..7ca43ec1 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -134,6 +134,7 @@ class CKeybindManager { static void exitHyprland(std::string); static void moveCurrentWorkspaceToMonitor(std::string); static void moveWorkspaceToMonitor(std::string); + static void focusWorkspaceOnCurrentMonitor(std::string); static void toggleSpecialWorkspace(std::string); static void forceRendererReload(std::string); static void resizeActive(std::string);