From 35e66dd10ac3548938354a05fd5f26289e1ecc15 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Tue, 5 Dec 2023 00:30:54 -0800 Subject: [PATCH 1/9] Update tracked hyprland version --- flake.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/flake.lock b/flake.lock index 68e9cd2..44ebbf5 100644 --- a/flake.lock +++ b/flake.lock @@ -9,11 +9,11 @@ "xdph": "xdph" }, "locked": { - "lastModified": 1699391198, - "narHash": "sha256-HrnlCdZBqqE37gFORapfSGEGcqhCyhX2aSMRnDEmR0k=", + "lastModified": 1701737536, + "narHash": "sha256-xSmfHhhCL9mAta5jKfcbJxYjCoD2MdLPBMjBUWvYAJI=", "owner": "hyprwm", "repo": "Hyprland", - "rev": "751d2851cc270c3322ffe2eb83c156e4298a0c0e", + "rev": "3bb9c7c5cf4f2ee30bf821501499f2308d616f94", "type": "github" }, "original": { @@ -49,11 +49,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": { @@ -87,18 +87,18 @@ "flake": false, "locked": { "host": "gitlab.freedesktop.org", - "lastModified": 1697909146, - "narHash": "sha256-jU0I6FoCKnj4zIBL4daosFWh81U1fM719Z6cae8PxSY=", + "lastModified": 1701368958, + "narHash": "sha256-7kvyoA91etzVEl9mkA/EJfB6z/PltxX7Xc4gcr7/xlo=", "owner": "wlroots", "repo": "wlroots", - "rev": "47bf87ade2bd32395615a385ebde1fefbcdf79a2", + "rev": "5d639394f3e83b01596dcd166a44a9a1a2583350", "type": "gitlab" }, "original": { "host": "gitlab.freedesktop.org", "owner": "wlroots", "repo": "wlroots", - "rev": "47bf87ade2bd32395615a385ebde1fefbcdf79a2", + "rev": "5d639394f3e83b01596dcd166a44a9a1a2583350", "type": "gitlab" } }, @@ -118,11 +118,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 92244e72858a9a0df28db20fb80b94a36f0a9b92 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Tue, 5 Dec 2023 00:48:26 -0800 Subject: [PATCH 2/9] Add hyprland version compatibility check --- CMakeLists.txt | 6 ++++++ compile_commands_bear.sh | 2 +- src/main.cpp | 15 +++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d886f50..e4e83ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,12 @@ add_library(hy3 SHARED src/SelectionHook.cpp ) +option(HY3_NO_VERSION_CHECK "Disable hyprland version check" FALSE) + +if (HY3_NO_VERSION_CHECK) + target_compile_definitions(hy3 PRIVATE -DHY3_NO_VERSION_CHECK=TRUE) +endif() + target_include_directories(hy3 PRIVATE ${DEPS_INCLUDE_DIRS}) install(TARGETS hy3 LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/compile_commands_bear.sh b/compile_commands_bear.sh index 8803482..83b4946 100755 --- a/compile_commands_bear.sh +++ b/compile_commands_bear.sh @@ -1,4 +1,4 @@ rm -rf build -cmake -DCMAKE_BUILD_TYPE=Debug -B build bear -- cmake --build build +cmake -DCMAKE_BUILD_TYPE=Debug -DHY3_NO_VERSION_CHECK=TRUE -B build sed -i 's/-std=gnu++23/-std=gnu++2b/g' compile_commands.json diff --git a/src/main.cpp b/src/main.cpp index f4e9c9e..b0820f4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,9 @@ #include +#include #include #include +#include #include "SelectionHook.hpp" #include "dispatchers.hpp" @@ -12,6 +14,19 @@ APICALL EXPORT std::string PLUGIN_API_VERSION() { return HYPRLAND_API_VERSION; } APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { PHANDLE = handle; +#ifndef HY3_NO_VERSION_CHECK + if (GIT_COMMIT_HASH != std::string(__hyprland_api_get_hash())) { + HyprlandAPI::addNotification( + PHANDLE, + "[hy3] Hy3 was compiled for a different version of hyprland; refusing to start.", + CColor {1.0, 0.2, 0.2, 1.0}, + 10000 + ); + + throw std::runtime_error("[hy3] target hyprland version mismatch"); + } +#endif + selection_hook::init(); #define CONF(NAME, TYPE, VALUE) \ From 6a89b574c7c01aab1b926144fbbfaab4e9aa183a Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Wed, 6 Dec 2023 01:43:34 -0800 Subject: [PATCH 3/9] Fix getNextWindowCandidate not considering fullscreen or floating windows --- src/Hy3Layout.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp index 1406272..981a2f2 100644 --- a/src/Hy3Layout.cpp +++ b/src/Hy3Layout.cpp @@ -3,6 +3,7 @@ #include #include +#include #include "Hy3Layout.hpp" #include "SelectionHook.hpp" @@ -689,6 +690,24 @@ void Hy3Layout::alterSplitRatio(CWindow* pWindow, float delta, bool exact) { std::string Hy3Layout::getLayoutName() { return "hy3"; } CWindow* Hy3Layout::getNextWindowCandidate(CWindow* window) { + auto* workspace = g_pCompositor->getWorkspaceByID(window->m_iWorkspaceID); + + if (workspace->m_bHasFullscreenWindow) { + return g_pCompositor->getFullscreenWindowOnWorkspace(window->m_iWorkspaceID); + } + + // return the first floating window on the same workspace that has not asked not to be focused + if (window->m_bIsFloating) { + for (std::unique_ptr& w: g_pCompositor->m_vWindows | std::views::reverse) { + if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 + && w->m_iWorkspaceID == window->m_iWorkspaceID && !w->m_bX11ShouldntFocus + && !w->m_bNoFocus && w.get() != window) + { + return w.get(); + } + } + } + auto* node = this->getWorkspaceFocusedNode(window->m_iWorkspaceID, true); if (node == nullptr) return nullptr; From c727ad11e3cef6fcf7a3f6864bc56c2a9cfd40fe Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Wed, 6 Dec 2023 02:55:12 -0800 Subject: [PATCH 4/9] Add floating window support to hy3:movefocus --- src/Hy3Layout.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp index 981a2f2..e26a054 100644 --- a/src/Hy3Layout.cpp +++ b/src/Hy3Layout.cpp @@ -698,7 +698,7 @@ CWindow* Hy3Layout::getNextWindowCandidate(CWindow* window) { // return the first floating window on the same workspace that has not asked not to be focused if (window->m_bIsFloating) { - for (std::unique_ptr& w: g_pCompositor->m_vWindows | std::views::reverse) { + for (auto& w: g_pCompositor->m_vWindows | std::views::reverse) { if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == window->m_iWorkspaceID && !w->m_bX11ShouldntFocus && !w->m_bNoFocus && w.get() != window) @@ -937,10 +937,53 @@ void Hy3Layout::shiftWindow(int workspace, ShiftDirection direction, bool once, } void Hy3Layout::shiftFocus(int workspace, ShiftDirection direction, bool visible) { + auto* current_window = g_pCompositor->m_pLastWindow; + auto* p_workspace = g_pCompositor->getWorkspaceByID(current_window->m_iWorkspaceID); + if (p_workspace->m_bHasFullscreenWindow) return; + + if (current_window != nullptr && current_window->m_bIsFloating) { + CWindow* next_window = nullptr; + double next_distance = -1; + + for (auto& w: g_pCompositor->m_vWindows) { + if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 + && w->m_iWorkspaceID == current_window->m_iWorkspaceID && !w->m_bX11ShouldntFocus + && !w->m_bNoFocus && w.get() != current_window) + { + double distance = 0; + + auto cpos = current_window->m_vRealPosition.vec() + (current_window->m_vRealSize.vec() / 2); + auto tpos = w->m_vRealPosition.vec() + (w->m_vRealSize.vec() / 2); + + auto x_offset = tpos.x - cpos.x; + auto y_offset = tpos.y - cpos.y; + + if (abs(x_offset) > abs(y_offset)) { + if (x_offset < 0 && direction == ShiftDirection::Left) distance = -x_offset; + else if (x_offset > 0 && direction == ShiftDirection::Right) distance = x_offset; + } else { + if (y_offset < 0 && direction == ShiftDirection::Up) distance = -y_offset; + else if (y_offset > 0 && direction == ShiftDirection::Down) distance = y_offset; + } + + if (distance <= 0) continue; + + if (next_distance == -1 || distance < next_distance) { + next_window = w.get(); + next_distance = distance; + } + } + } + + if (next_window != nullptr) g_pCompositor->focusWindow(next_window); + return; + } + auto* node = this->getWorkspaceFocusedNode(workspace); if (node == nullptr) return; auto* target = this->shiftOrGetFocus(*node, direction, false, false, visible); + if (target != nullptr) { target->focus(); while (target->parent != nullptr) target = target->parent; From f71ac3756570abf028a4c9fc5a07b58a09ba5072 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Wed, 6 Dec 2023 02:58:03 -0800 Subject: [PATCH 5/9] Use hyprland algorithm to find floating window to focus in direction --- src/Hy3Layout.cpp | 39 +++++++-------------------------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp index e26a054..7182bd8 100644 --- a/src/Hy3Layout.cpp +++ b/src/Hy3Layout.cpp @@ -942,38 +942,13 @@ void Hy3Layout::shiftFocus(int workspace, ShiftDirection direction, bool visible if (p_workspace->m_bHasFullscreenWindow) return; if (current_window != nullptr && current_window->m_bIsFloating) { - CWindow* next_window = nullptr; - double next_distance = -1; - - for (auto& w: g_pCompositor->m_vWindows) { - if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 - && w->m_iWorkspaceID == current_window->m_iWorkspaceID && !w->m_bX11ShouldntFocus - && !w->m_bNoFocus && w.get() != current_window) - { - double distance = 0; - - auto cpos = current_window->m_vRealPosition.vec() + (current_window->m_vRealSize.vec() / 2); - auto tpos = w->m_vRealPosition.vec() + (w->m_vRealSize.vec() / 2); - - auto x_offset = tpos.x - cpos.x; - auto y_offset = tpos.y - cpos.y; - - if (abs(x_offset) > abs(y_offset)) { - if (x_offset < 0 && direction == ShiftDirection::Left) distance = -x_offset; - else if (x_offset > 0 && direction == ShiftDirection::Right) distance = x_offset; - } else { - if (y_offset < 0 && direction == ShiftDirection::Up) distance = -y_offset; - else if (y_offset > 0 && direction == ShiftDirection::Down) distance = y_offset; - } - - if (distance <= 0) continue; - - if (next_distance == -1 || distance < next_distance) { - next_window = w.get(); - next_distance = distance; - } - } - } + auto* next_window = g_pCompositor->getWindowInDirection( + current_window, + direction == ShiftDirection::Left ? 'l' + : direction == ShiftDirection::Up ? 'u' + : direction == ShiftDirection::Down ? 'd' + : 'r' + ); if (next_window != nullptr) g_pCompositor->focusWindow(next_window); return; From b341fe60a75eae94a2ee612387dafd280ed62208 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sun, 10 Dec 2023 01:02:23 -0800 Subject: [PATCH 6/9] Fix crash when moving focus of a node containing multiple windows --- src/Hy3Layout.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp index 7182bd8..9cd184e 100644 --- a/src/Hy3Layout.cpp +++ b/src/Hy3Layout.cpp @@ -938,20 +938,23 @@ void Hy3Layout::shiftWindow(int workspace, ShiftDirection direction, bool once, void Hy3Layout::shiftFocus(int workspace, ShiftDirection direction, bool visible) { auto* current_window = g_pCompositor->m_pLastWindow; - auto* p_workspace = g_pCompositor->getWorkspaceByID(current_window->m_iWorkspaceID); - if (p_workspace->m_bHasFullscreenWindow) return; - if (current_window != nullptr && current_window->m_bIsFloating) { - auto* next_window = g_pCompositor->getWindowInDirection( - current_window, - direction == ShiftDirection::Left ? 'l' - : direction == ShiftDirection::Up ? 'u' - : direction == ShiftDirection::Down ? 'd' - : 'r' - ); + if (current_window != nullptr) { + auto* p_workspace = g_pCompositor->getWorkspaceByID(current_window->m_iWorkspaceID); + if (p_workspace->m_bHasFullscreenWindow) return; - if (next_window != nullptr) g_pCompositor->focusWindow(next_window); - return; + if (current_window->m_bIsFloating) { + auto* next_window = g_pCompositor->getWindowInDirection( + current_window, + direction == ShiftDirection::Left ? 'l' + : direction == ShiftDirection::Up ? 'u' + : direction == ShiftDirection::Down ? 'd' + : 'r' + ); + + if (next_window != nullptr) g_pCompositor->focusWindow(next_window); + return; + } } auto* node = this->getWorkspaceFocusedNode(workspace); From 102e652fe926d1da2a18d22928a69760580d7751 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sun, 10 Dec 2023 16:54:35 -0800 Subject: [PATCH 7/9] Fix tab bars not rendering on non 1.0 dpi values Closes #48 --- src/TabGroup.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/TabGroup.cpp b/src/TabGroup.cpp index 28ced1d..8622113 100644 --- a/src/TabGroup.cpp +++ b/src/TabGroup.cpp @@ -548,8 +548,9 @@ void Hy3TabGroup::renderTabBar() { auto scaled_size = Vector2D(std::round(size.x * scale), std::round(size.y * scale)); wlr_box box = {scaled_pos.x, scaled_pos.y, scaled_size.x, scaled_size.y}; - if (scaled_pos.x > monitor_size.x || scaled_pos.y > monitor_size.y - || scaled_pos.x + scaled_size.x < 0 || scaled_pos.y + scaled_size.y < 0) + // monitor size is not scaled + if (pos.x > monitor_size.x || pos.y > monitor_size.y || scaled_pos.x + scaled_size.x < 0 + || scaled_pos.y + scaled_size.y < 0) return; if (!this->bar.damaged) { From 4830a2cf3c5e39865b97c504ba3f429d9cb2b684 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sun, 10 Dec 2023 17:00:35 -0800 Subject: [PATCH 8/9] Fix tab rounding on non 1.0 dpi values --- src/TabGroup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TabGroup.cpp b/src/TabGroup.cpp index 8622113..217b88e 100644 --- a/src/TabGroup.cpp +++ b/src/TabGroup.cpp @@ -142,7 +142,7 @@ void Hy3TabBarEntry::prepareTexture(float scale, CBox& box) { auto width = box.width; auto height = box.height; - auto rounding = std::min((double) *s_rounding, std::min(width * 0.5, height * 0.5)); + auto rounding = std::min((double) *s_rounding * scale, std::min(width * 0.5, height * 0.5)); if (this->texture.m_iTexID == 0 // clang-format off From fdb23665b90f547bffd4a3664fe21ea9a5863ab1 Mon Sep 17 00:00:00 2001 From: eriedaberrie Date: Sun, 10 Dec 2023 16:14:39 -0800 Subject: [PATCH 9/9] Fix over-correction of borders that are now window decorations --- flake.lock | 6 +++--- src/Hy3Layout.cpp | 9 ++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/flake.lock b/flake.lock index 44ebbf5..d7a752d 100644 --- a/flake.lock +++ b/flake.lock @@ -9,11 +9,11 @@ "xdph": "xdph" }, "locked": { - "lastModified": 1701737536, - "narHash": "sha256-xSmfHhhCL9mAta5jKfcbJxYjCoD2MdLPBMjBUWvYAJI=", + "lastModified": 1702236723, + "narHash": "sha256-zIEnimM1vhsFkz+Kubb8kJ6YgHuLe56pALOSJc6CMVY=", "owner": "hyprwm", "repo": "Hyprland", - "rev": "3bb9c7c5cf4f2ee30bf821501499f2308d616f94", + "rev": "167f2ed3b2bb18ceeabb831ac80b655ef8e16867", "type": "github" }, "original": { diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp index 9cd184e..6ad2d07 100644 --- a/src/Hy3Layout.cpp +++ b/src/Hy3Layout.cpp @@ -1441,7 +1441,6 @@ void Hy3Layout::applyNodeDataToWindow(Hy3Node* node, bool no_animation) { } // clang-format off - static const auto* border_size = &HyprlandAPI::getConfigValue(PHANDLE, "general:border_size")->intValue; static const auto* gaps_in = &HyprlandAPI::getConfigValue(PHANDLE, "general:gaps_in")->intValue; static const auto* single_window_no_gaps = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:no_gaps_when_only")->intValue; // clang-format on @@ -1462,9 +1461,6 @@ void Hy3Layout::applyNodeDataToWindow(Hy3Node* node, bool no_animation) { window->m_vSize = node->size; window->m_vPosition = node->position; - auto calcPos = window->m_vPosition + Vector2D(*border_size, *border_size); - auto calcSize = window->m_vSize - Vector2D(2 * *border_size, 2 * *border_size); - auto only_node = root_node->data.as_group.children.size() == 1 && root_node->data.as_group.children.front()->data.type == Hy3NodeType::Window; @@ -1491,6 +1487,9 @@ void Hy3Layout::applyNodeDataToWindow(Hy3Node* node, bool no_animation) { window->m_sSpecialRenderData.border = true; window->m_sSpecialRenderData.decorate = true; + auto calcPos = window->m_vPosition; + auto calcSize = window->m_vSize; + auto gaps_offset_topleft = Vector2D(*gaps_in, *gaps_in) + node->gap_topleft_offset; auto gaps_offset_bottomright = Vector2D(*gaps_in * 2, *gaps_in * 2) + node->gap_bottomright_offset + node->gap_topleft_offset; @@ -1500,7 +1499,7 @@ void Hy3Layout::applyNodeDataToWindow(Hy3Node* node, bool no_animation) { const auto reserved_area = window->getFullWindowReservedArea(); calcPos = calcPos + reserved_area.topLeft; - calcSize = calcSize - (reserved_area.topLeft - reserved_area.bottomRight); + calcSize = calcSize - (reserved_area.topLeft + reserved_area.bottomRight); CBox wb = {calcPos, calcSize}; wb.round();