From dc5a0224ce627436aba2e525d46767b1130f0868 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Mon, 29 Apr 2024 16:45:23 -0700 Subject: [PATCH] fixup: fix breakage after hyprland#5762 + improve Hy3NodeData repr Hy3NodeData now uses std::variant instead of a union, and all accesses are checked. --- flake.lock | 19 ++- flake.nix | 2 +- src/Hy3Layout.cpp | 330 +++++++++++++++++++------------------- src/Hy3Layout.hpp | 50 +++--- src/Hy3Node.cpp | 362 ++++++++++++++++++++++-------------------- src/Hy3Node.hpp | 38 ++--- src/SelectionHook.cpp | 6 +- src/TabGroup.cpp | 23 +-- src/TabGroup.hpp | 4 +- 9 files changed, 431 insertions(+), 403 deletions(-) diff --git a/flake.lock b/flake.lock index 7b5053a..50d25e8 100644 --- a/flake.lock +++ b/flake.lock @@ -41,16 +41,15 @@ "xdph": "xdph" }, "locked": { - "lastModified": 1713819507, - "narHash": "sha256-mG0kD8HmkCsHRkTBmqGb/QvM1vAvkAmB5p2H5XQ0zLo=", + "lastModified": 1714409407, + "narHash": "sha256-gc10Ag5O/s+EE24JZUXTpH4ogRsSyAfdgr7OvSNhQ8s=", "owner": "hyprwm", "repo": "Hyprland", - "rev": "da839f20f1b1a57ec78d6b041f8d1369150d253e", + "rev": "f2b03e9679bc1a091fecffd98b50a4179b5c7d43", "type": "github" }, "original": { "owner": "hyprwm", - "ref": "da839f20f1b1a57ec78d6b041f8d1369150d253e", "repo": "Hyprland", "type": "github" } @@ -117,11 +116,11 @@ ] }, "locked": { - "lastModified": 1713730424, - "narHash": "sha256-MqYjTvQCxwuDIuAaqIEuyqserm5PYr0auiHHPuYFN/k=", + "lastModified": 1714171579, + "narHash": "sha256-eaWDIvt8ufUKKz3Lc2a3PyemLJG1m9RYlF+HP3hWbaw=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "7c9c8adfe7e424faa0c5ce6e8be90157fda53c06", + "rev": "126dad854f22fe30e6b82cd21808e76903d90ac5", "type": "github" }, "original": { @@ -132,11 +131,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1713537308, - "narHash": "sha256-XtTSSIB2DA6tOv+l0FhvfDMiyCmhoRbNB+0SeInZkbk=", + "lastModified": 1713714899, + "narHash": "sha256-+z/XjO3QJs5rLE5UOf015gdVauVRQd2vZtsFkaXBq2Y=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5c24cf2f0a12ad855f444c30b2421d044120c66f", + "rev": "6143fc5eeb9c4f00163267708e26191d1e918932", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 998ea51..a375308 100644 --- a/flake.nix +++ b/flake.nix @@ -1,6 +1,6 @@ { inputs = { - hyprland.url = "github:hyprwm/Hyprland?ref=da839f20f1b1a57ec78d6b041f8d1369150d253e"; + hyprland.url = "github:hyprwm/Hyprland"; }; outputs = { self, hyprland, ... }: let diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp index ca60aa0..4bfcca8 100644 --- a/src/Hy3Layout.cpp +++ b/src/Hy3Layout.cpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -15,18 +16,18 @@ std::shared_ptr windowTitleHookPtr; std::shared_ptr urgentHookPtr; std::shared_ptr tickHookPtr; -bool performContainment(Hy3Node& node, bool contained, CWindow* window) { - if (node.data.type == Hy3NodeType::Group) { - auto& group = node.data.as_group; +bool performContainment(Hy3Node& node, bool contained, PHLWINDOW& window) { + if (node.data.is_group()) { + auto& group = node.data.as_group(); contained |= group.containment; - auto iter = node.data.as_group.children.begin(); - while (iter != node.data.as_group.children.end()) { - switch ((*iter)->data.type) { + auto iter = group.children.begin(); + while (iter != group.children.end()) { + switch ((*iter)->data.type()) { case Hy3NodeType::Group: return performContainment(**iter, contained, window); case Hy3NodeType::Window: if (contained) { - auto wpid = (*iter)->data.as_window->getPID(); + auto wpid = (*iter)->data.as_window()->getPID(); auto ppid = getPPIDof(window->getPID()); while (ppid > 10) { // `> 10` yoinked from HL swallow if (ppid == wpid) { @@ -58,7 +59,7 @@ bool performContainment(Hy3Node& node, bool contained, CWindow* window) { return false; } -void Hy3Layout::onWindowCreated(CWindow* window, eDirection direction) { +void Hy3Layout::onWindowCreated(PHLWINDOW window, eDirection direction) { for (auto& node: this->nodes) { if (node.parent == nullptr && performContainment(node, false, window)) { return; @@ -68,11 +69,11 @@ void Hy3Layout::onWindowCreated(CWindow* window, eDirection direction) { IHyprLayout::onWindowCreated(window, direction); } -void Hy3Layout::onWindowCreatedTiling(CWindow* window, eDirection) { +void Hy3Layout::onWindowCreatedTiling(PHLWINDOW window, eDirection) { hy3_log( LOG, "onWindowCreatedTiling called with window {:x} (floating: {}, monitor: {}, workspace: {})", - (uintptr_t) window, + (uintptr_t) window.get(), window->m_bIsFloating, window->m_iMonitorID, window->m_pWorkspace->m_iID @@ -85,7 +86,7 @@ void Hy3Layout::onWindowCreatedTiling(CWindow* window, eDirection) { hy3_log( ERR, "onWindowCreatedTiling called with a window ({:x}) that is already tiled (node: {:x})", - (uintptr_t) window, + (uintptr_t) window.get(), (uintptr_t) existing ); return; @@ -142,16 +143,15 @@ void Hy3Layout::insertNode(Hy3Node& node) { } if (opening_after == nullptr) { - if (g_pCompositor->m_pLastWindow != nullptr - && g_pCompositor->m_pLastWindow->m_pWorkspace == node.workspace - && !g_pCompositor->m_pLastWindow->m_bIsFloating - && (node.data.type == Hy3NodeType::Window - || g_pCompositor->m_pLastWindow != node.data.as_window) - && g_pCompositor->m_pLastWindow->m_bIsMapped) + auto last_window = g_pCompositor->m_pLastWindow.lock(); + if (last_window != nullptr && last_window->m_pWorkspace == node.workspace + && !last_window->m_bIsFloating + && (node.data.is_window() || last_window != node.data.as_window()) + && last_window->m_bIsMapped) { - opening_after = this->getNodeFromWindow(g_pCompositor->m_pLastWindow); + opening_after = this->getNodeFromWindow(last_window); } else { - auto* mouse_window = g_pCompositor->vectorToWindowUnified( + auto mouse_window = g_pCompositor->vectorToWindowUnified( g_pInputManager->getMouseCoordsInternal(), RESERVED_EXTENTS | INPUT_EXTENTS ); @@ -163,8 +163,8 @@ void Hy3Layout::insertNode(Hy3Node& node) { } if (opening_after != nullptr - && ((node.data.type == Hy3NodeType::Group - && (opening_after == &node || node.data.as_group.hasChild(opening_after))) + && ((node.data.is_group() + && (opening_after == &node || node.data.as_group().hasChild(opening_after))) || opening_after->reparenting)) { opening_after = nullptr; @@ -202,14 +202,14 @@ void Hy3Layout::insertNode(Hy3Node& node) { .layout = this, }); - parent.data.as_group.children.push_back(&this->nodes.back()); + parent.data.as_group().children.push_back(&this->nodes.back()); } opening_into = &this->nodes.back(); } } - if (opening_into->data.type != Hy3NodeType::Group) { + if (opening_into->data.is_window()) { hy3_log(ERR, "opening_into node ({:x}) was not a group node", (uintptr_t) opening_into); errorNotif(); return; @@ -236,7 +236,7 @@ void Hy3Layout::insertNode(Hy3Node& node) { this->updateAutotileWorkspaces(); - auto& target_group = opening_into->data.as_group; + auto& target_group = opening_into->data.as_group(); if (*at_enable && opening_after != nullptr && target_group.children.size() > 1 && target_group.layout != Hy3GroupLayout::Tabbed && this->shouldAutotileWorkspace(opening_into->workspace)) @@ -261,9 +261,9 @@ void Hy3Layout::insertNode(Hy3Node& node) { node.reparenting = false; if (opening_after == nullptr) { - opening_into->data.as_group.children.push_back(&node); + opening_into->data.as_group().children.push_back(&node); } else { - auto& children = opening_into->data.as_group.children; + auto& children = opening_into->data.as_group().children; auto iter = std::find(children.begin(), children.end(), opening_after); auto iter2 = std::next(iter); children.insert(iter2, &node); @@ -281,7 +281,7 @@ void Hy3Layout::insertNode(Hy3Node& node) { opening_into->recalcSizePosRecursive(); } -void Hy3Layout::onWindowRemovedTiling(CWindow* window) { +void Hy3Layout::onWindowRemovedTiling(PHLWINDOW window) { static const auto node_collapse_policy = ConfigValue("plugin:hy3:node_collapse_policy"); @@ -292,7 +292,7 @@ void Hy3Layout::onWindowRemovedTiling(CWindow* window) { hy3_log( LOG, "removing window ({:x} as node {:x}) from node {:x}", - (uintptr_t) window, + (uintptr_t) window.get(), (uintptr_t) node, (uintptr_t) node->parent ); @@ -310,17 +310,16 @@ void Hy3Layout::onWindowRemovedTiling(CWindow* window) { this->nodes.remove(*node); if (expand_actor != nullptr) expand_actor->recalcSizePosRecursive(); - auto& group = parent->data.as_group; - if (parent != nullptr) { + auto& group = parent->data.as_group(); parent->recalcSizePosRecursive(); // returns if a given node is a group that can be collapsed given the current config auto node_is_collapsible = [](Hy3Node* node) { - if (node->data.type != Hy3NodeType::Group) return false; + if (node->data.is_window()) return false; if (*node_collapse_policy == 0) return true; else if (*node_collapse_policy == 1) return false; - return node->parent->data.as_group.layout != Hy3GroupLayout::Tabbed; + return node->parent->data.as_group().layout != Hy3GroupLayout::Tabbed; }; if (group.children.size() == 1 @@ -337,14 +336,14 @@ void Hy3Layout::onWindowRemovedTiling(CWindow* window) { } } -void Hy3Layout::onWindowFocusChange(CWindow* window) { +void Hy3Layout::onWindowFocusChange(PHLWINDOW window) { auto* node = this->getNodeFromWindow(window); if (node == nullptr) return; hy3_log( TRACE, "changing window focus to window {:x} as node {:x}", - (uintptr_t) window, + (uintptr_t) window.get(), (uintptr_t) node ); @@ -353,7 +352,7 @@ void Hy3Layout::onWindowFocusChange(CWindow* window) { node->recalcSizePosRecursive(); } -bool Hy3Layout::isWindowTiled(CWindow* window) { +bool Hy3Layout::isWindowTiled(PHLWINDOW window) { return this->getNodeFromWindow(window) != nullptr; } @@ -386,7 +385,7 @@ void Hy3Layout::recalculateMonitor(const int& monitor_id) { } } -void Hy3Layout::recalculateWindow(CWindow* window) { +void Hy3Layout::recalculateWindow(PHLWINDOW window) { auto* node = this->getNodeFromWindow(window); if (node == nullptr) return; node->recalcSizePosRecursive(); @@ -402,9 +401,9 @@ ShiftDirection reverse(ShiftDirection direction) { } } -void Hy3Layout::resizeActiveWindow(const Vector2D& delta, eRectCorner corner, CWindow* pWindow) { - auto window = pWindow ? pWindow : g_pCompositor->m_pLastWindow; - if (!g_pCompositor->windowValidMapped(window)) return; +void Hy3Layout::resizeActiveWindow(const Vector2D& delta, eRectCorner corner, PHLWINDOW pWindow) { + auto window = pWindow ? pWindow : g_pCompositor->m_pLastWindow.lock(); + if (!valid(window)) return; auto* node = this->getNodeFromWindow(window); @@ -427,9 +426,9 @@ void Hy3Layout::resizeActiveWindow(const Vector2D& delta, eRectCorner corner, CW ); Vector2D resize_delta = delta; - bool node_is_root = (node->data.type == Hy3NodeType::Group && node->parent == nullptr) - || (node->data.type == Hy3NodeType::Window - && (node->parent == nullptr || node->parent->parent == nullptr)); + bool node_is_root = + (node->data.is_group() && node->parent == nullptr) + || (node->data.is_window() && (node->parent == nullptr || node->parent->parent == nullptr)); if (node_is_root) { if (display_left && display_right) resize_delta.x = 0; @@ -490,11 +489,10 @@ void Hy3Layout::resizeActiveWindow(const Vector2D& delta, eRectCorner corner, CW } void Hy3Layout::fullscreenRequestForWindow( - CWindow* window, + PHLWINDOW window, eFullscreenMode fullscreen_mode, bool on ) { - if (!g_pCompositor->windowValidMapped(window)) return; if (on == window->m_bIsFullscreen || window->m_pWorkspace->m_bIsSpecialWorkspace) return; const auto monitor = g_pCompositor->getMonitorFromID(window->m_iMonitorID); @@ -575,7 +573,7 @@ std::any Hy3Layout::layoutMessage(SLayoutMessageHeader header, std::string conte if (content == "togglesplit") { auto* node = this->getNodeFromWindow(header.pWindow); if (node != nullptr && node->parent != nullptr) { - auto& layout = node->parent->data.as_group.layout; + auto& layout = node->parent->data.as_group().layout; switch (layout) { case Hy3GroupLayout::SplitH: @@ -594,13 +592,13 @@ std::any Hy3Layout::layoutMessage(SLayoutMessageHeader header, std::string conte return ""; } -SWindowRenderLayoutHints Hy3Layout::requestRenderHints(CWindow* window) { return {}; } +SWindowRenderLayoutHints Hy3Layout::requestRenderHints(PHLWINDOW window) { return {}; } -void Hy3Layout::switchWindows(CWindow* pWindowA, CWindow* pWindowB) { +void Hy3Layout::switchWindows(PHLWINDOW pWindowA, PHLWINDOW pWindowB) { // todo } -void Hy3Layout::moveWindowTo(CWindow* window, const std::string& direction, bool silent) { +void Hy3Layout::moveWindowTo(PHLWINDOW window, const std::string& direction, bool silent) { // todo: support silent auto* node = this->getNodeFromWindow(window); if (node == nullptr) return; @@ -615,13 +613,13 @@ void Hy3Layout::moveWindowTo(CWindow* window, const std::string& direction, bool this->shiftNode(*node, shift, false, false); } -void Hy3Layout::alterSplitRatio(CWindow* pWindow, float delta, bool exact) { +void Hy3Layout::alterSplitRatio(PHLWINDOW pWindow, float delta, bool exact) { // todo } std::string Hy3Layout::getLayoutName() { return "hy3"; } -CWindow* Hy3Layout::getNextWindowCandidate(CWindow* window) { +PHLWINDOW Hy3Layout::getNextWindowCandidate(PHLWINDOW window) { if (window->m_pWorkspace->m_bHasFullscreenWindow) { return g_pCompositor->getFullscreenWindowOnWorkspace(window->m_pWorkspace->m_iID); } @@ -631,9 +629,9 @@ CWindow* Hy3Layout::getNextWindowCandidate(CWindow* window) { 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_pWorkspace == window->m_pWorkspace && !w->m_bX11ShouldntFocus - && !w->m_sAdditionalConfigData.noFocus && w.get() != window) + && !w->m_sAdditionalConfigData.noFocus && w != window) { - return w.get(); + return w; } } } @@ -641,26 +639,26 @@ CWindow* Hy3Layout::getNextWindowCandidate(CWindow* window) { auto* node = this->getWorkspaceFocusedNode(window->m_pWorkspace, true); if (node == nullptr) return nullptr; - switch (node->data.type) { - case Hy3NodeType::Window: return node->data.as_window; - case Hy3NodeType::Group: return nullptr; - default: return nullptr; + if (node->data.is_window()) { + return node->data.as_window(); + } else { + return nullptr; } } -void Hy3Layout::replaceWindowDataWith(CWindow* from, CWindow* to) { +void Hy3Layout::replaceWindowDataWith(PHLWINDOW from, PHLWINDOW to) { auto* node = this->getNodeFromWindow(from); if (node == nullptr) return; - node->data.as_window = to; + node->data.as_window() = to; this->applyNodeDataToWindow(node); } -bool Hy3Layout::isWindowReachable(CWindow* window) { +bool Hy3Layout::isWindowReachable(PHLWINDOW window) { return this->getNodeFromWindow(window) != nullptr || IHyprLayout::isWindowReachable(window); } -void Hy3Layout::bringWindowToTop(CWindow* window) { +void Hy3Layout::bringWindowToTop(PHLWINDOW window) { auto node = this->getNodeFromWindow(window); if (node == nullptr) return; node->bringToTop(); @@ -671,12 +669,17 @@ void Hy3Layout::onEnable() { if (window->isHidden() || !window->m_bIsMapped || window->m_bFadingOut || window->m_bIsFloating) continue; - this->onWindowCreatedTiling(window.get()); + this->onWindowCreatedTiling(window); } renderHookPtr = HyprlandAPI::registerCallbackDynamic(PHANDLE, "render", &Hy3Layout::renderHook); - windowTitleHookPtr = HyprlandAPI::registerCallbackDynamic(PHANDLE, "windowTitle", &Hy3Layout::windowGroupUpdateRecursiveHook); - urgentHookPtr = HyprlandAPI::registerCallbackDynamic(PHANDLE, "urgent", &Hy3Layout::windowGroupUrgentHook); + windowTitleHookPtr = HyprlandAPI::registerCallbackDynamic( + PHANDLE, + "windowTitle", + &Hy3Layout::windowGroupUpdateRecursiveHook + ); + urgentHookPtr = + HyprlandAPI::registerCallbackDynamic(PHANDLE, "urgent", &Hy3Layout::windowGroupUrgentHook); tickHookPtr = HyprlandAPI::registerCallbackDynamic(PHANDLE, "tick", &Hy3Layout::tickHook); selection_hook::enable(); } @@ -689,8 +692,8 @@ void Hy3Layout::onDisable() { selection_hook::disable(); for (auto& node: this->nodes) { - if (node.data.type == Hy3NodeType::Window) { - node.data.as_window->setHidden(false); + if (node.data.is_window()) { + node.data.as_window()->setHidden(false); } } @@ -757,7 +760,7 @@ void Hy3Layout::makeGroupOn( if (node == nullptr) return; if (node->parent != nullptr) { - auto& group = node->parent->data.as_group; + auto& group = node->parent->data.as_group(); if (group.children.size() == 1) { group.setLayout(layout); group.setEphemeral(ephemeral); @@ -778,7 +781,7 @@ void Hy3Layout::makeOppositeGroupOn(Hy3Node* node, GroupEphemeralityOption ephem return; } - auto& group = node->parent->data.as_group; + auto& group = node->parent->data.as_group(); auto layout = group.layout == Hy3GroupLayout::SplitH ? Hy3GroupLayout::SplitV : Hy3GroupLayout::SplitH; @@ -798,7 +801,7 @@ void Hy3Layout::changeGroupOn(Hy3Node& node, Hy3GroupLayout layout) { return; } - auto& group = node.parent->data.as_group; + auto& group = node.parent->data.as_group(); group.setLayout(layout); node.parent->updateTabBarRecursive(); node.parent->recalcSizePosRecursive(); @@ -807,7 +810,7 @@ void Hy3Layout::changeGroupOn(Hy3Node& node, Hy3GroupLayout layout) { void Hy3Layout::untabGroupOn(Hy3Node& node) { if (node.parent == nullptr) return; - auto& group = node.parent->data.as_group; + auto& group = node.parent->data.as_group(); if (group.layout != Hy3GroupLayout::Tabbed) return; changeGroupOn(node, group.previous_nontab_layout); @@ -816,7 +819,7 @@ void Hy3Layout::untabGroupOn(Hy3Node& node) { void Hy3Layout::toggleTabGroupOn(Hy3Node& node) { if (node.parent == nullptr) return; - auto& group = node.parent->data.as_group; + auto& group = node.parent->data.as_group(); if (group.layout != Hy3GroupLayout::Tabbed) changeGroupOn(node, Hy3GroupLayout::Tabbed); else changeGroupOn(node, group.previous_nontab_layout); } @@ -824,7 +827,7 @@ void Hy3Layout::toggleTabGroupOn(Hy3Node& node) { void Hy3Layout::changeGroupToOppositeOn(Hy3Node& node) { if (node.parent == nullptr) return; - auto& group = node.parent->data.as_group; + auto& group = node.parent->data.as_group(); if (group.layout == Hy3GroupLayout::Tabbed) { group.setLayout(group.previous_nontab_layout); @@ -840,16 +843,16 @@ void Hy3Layout::changeGroupToOppositeOn(Hy3Node& node) { void Hy3Layout::changeGroupEphemeralityOn(Hy3Node& node, bool ephemeral) { if (node.parent == nullptr) return; - auto& group = node.parent->data.as_group; + auto& group = node.parent->data.as_group(); group.setEphemeral( ephemeral ? GroupEphemeralityOption::ForceEphemeral : GroupEphemeralityOption::Standard ); } void Hy3Layout::shiftNode(Hy3Node& node, ShiftDirection direction, bool once, bool visible) { - if (once && node.parent != nullptr && node.parent->data.as_group.children.size() == 1) { + if (once && node.parent != nullptr && node.parent->data.as_group().children.size() == 1) { if (node.parent->parent == nullptr) { - node.parent->data.as_group.setLayout(Hy3GroupLayout::SplitH); + node.parent->data.as_group().setLayout(Hy3GroupLayout::SplitH); node.parent->recalcSizePosRecursive(); } else { auto* node2 = node.parent; @@ -876,13 +879,13 @@ void Hy3Layout::shiftWindow( } void Hy3Layout::shiftFocus(const PHLWORKSPACE& workspace, ShiftDirection direction, bool visible) { - auto* current_window = g_pCompositor->m_pLastWindow; + auto current_window = g_pCompositor->m_pLastWindow.lock(); if (current_window != nullptr) { if (current_window->m_pWorkspace->m_bHasFullscreenWindow) return; if (current_window->m_bIsFloating) { - auto* next_window = g_pCompositor->getWindowInDirection( + auto next_window = g_pCompositor->getWindowInDirection( current_window, direction == ShiftDirection::Left ? 'l' : direction == ShiftDirection::Up ? 'u' @@ -910,13 +913,13 @@ void Hy3Layout::shiftFocus(const PHLWORKSPACE& workspace, ShiftDirection directi void changeNodeWorkspaceRecursive(Hy3Node& node, const PHLWORKSPACE& workspace) { node.workspace = workspace; - if (node.data.type == Hy3NodeType::Window) { - auto* window = node.data.as_window; + if (node.data.is_window()) { + auto window = node.data.as_window(); window->moveToWorkspace(workspace); window->updateToplevel(); window->updateDynamicRules(); } else { - for (auto* child: node.data.as_group.children) { + for (auto* child: node.data.as_group().children) { changeNodeWorkspaceRecursive(*child, workspace); } } @@ -936,7 +939,7 @@ void Hy3Layout::moveNodeToWorkspace(const PHLWORKSPACE& origin, std::string wsna if (origin == workspace) return; auto* node = this->getWorkspaceFocusedNode(origin); - auto* focused_window = g_pCompositor->m_pLastWindow; + auto focused_window = g_pCompositor->m_pLastWindow.lock(); auto* focused_window_node = this->getNodeFromWindow(focused_window); auto origin_ws = node != nullptr ? node->workspace @@ -1013,14 +1016,14 @@ void Hy3Layout::changeFocus(const PHLWORKSPACE& workspace, FocusShift shift) { } return; case FocusShift::Lower: - if (node->data.type == Hy3NodeType::Group && node->data.as_group.focused_child != nullptr) - node->data.as_group.focused_child->focus(); + if (node->data.is_group() && node->data.as_group().focused_child != nullptr) + node->data.as_group().focused_child->focus(); return; case FocusShift::Tab: // make sure we go up at least one level if (node->parent != nullptr) node = node->parent; while (node->parent != nullptr) { - if (node->data.as_group.layout == Hy3GroupLayout::Tabbed) { + if (node->data.as_group().layout == Hy3GroupLayout::Tabbed) { node->focus(); return; } @@ -1032,7 +1035,7 @@ void Hy3Layout::changeFocus(const PHLWORKSPACE& workspace, FocusShift shift) { // make sure we go up at least one level if (node->parent != nullptr) node = node->parent; while (node->parent != nullptr) { - if (node->parent->data.as_group.layout == Hy3GroupLayout::Tabbed) { + if (node->parent->data.as_group().layout == Hy3GroupLayout::Tabbed) { node->focus(); return; } @@ -1043,8 +1046,8 @@ void Hy3Layout::changeFocus(const PHLWORKSPACE& workspace, FocusShift shift) { } bottom: - while (node->data.type == Hy3NodeType::Group && node->data.as_group.focused_child != nullptr) { - node = node->data.as_group.focused_child; + while (node->data.is_group() && node->data.as_group().focused_child != nullptr) { + node = node->data.as_group().focused_child; } node->focus(); @@ -1067,19 +1070,19 @@ Hy3Node* findTabBarAt(Hy3Node& node, Vector2D pos, Hy3Node** focused_node) { inset += gaps_in->left; } - if (node.data.type == Hy3NodeType::Group) { + if (node.data.is_group()) { if (node.hidden) return nullptr; // note: tab bar clicks ignore animations if (node.position.x > pos.x || node.position.y > pos.y || node.position.x + node.size.x < pos.x || node.position.y + node.size.y < pos.y) return nullptr; - if (node.data.as_group.layout == Hy3GroupLayout::Tabbed - && node.data.as_group.tab_bar != nullptr) - { + auto& group = node.data.as_group(); + + if (group.layout == Hy3GroupLayout::Tabbed && node.data.as_group().tab_bar != nullptr) { if (pos.y < node.position.y + node.gap_topleft_offset.y + inset) { - auto& children = node.data.as_group.children; - auto& tab_bar = *node.data.as_group.tab_bar; + auto& children = group.children; + auto& tab_bar = *group.tab_bar; auto size = tab_bar.size.value(); auto x = pos.x - tab_bar.pos.value().x; @@ -1099,11 +1102,11 @@ Hy3Node* findTabBarAt(Hy3Node& node, Vector2D pos, Hy3Node** focused_node) { } } - if (node.data.as_group.focused_child != nullptr) { - return findTabBarAt(*node.data.as_group.focused_child, pos, focused_node); + if (group.focused_child != nullptr) { + return findTabBarAt(*group.focused_child, pos, focused_node); } } else { - for (auto child: node.data.as_group.children) { + for (auto child: group.children) { if (findTabBarAt(*child, pos, focused_node)) return child; } } @@ -1144,22 +1147,21 @@ void Hy3Layout::focusTab( tab_node = this->getWorkspaceFocusedNode(workspace); if (tab_node == nullptr) return; - while (tab_node != nullptr && tab_node->data.as_group.layout != Hy3GroupLayout::Tabbed + while (tab_node != nullptr && tab_node->data.as_group().layout != Hy3GroupLayout::Tabbed && tab_node->parent != nullptr) tab_node = tab_node->parent; - if (tab_node == nullptr || tab_node->data.type != Hy3NodeType::Group - || tab_node->data.as_group.layout != Hy3GroupLayout::Tabbed) + if (tab_node == nullptr || tab_node->data.is_window() + || tab_node->data.as_group().layout != Hy3GroupLayout::Tabbed) return; } hastab: if (target != TabFocus::MouseLocation) { - if (tab_node->data.as_group.focused_child == nullptr - || tab_node->data.as_group.children.size() < 2) - return; + auto& group = tab_node->data.as_group(); + if (group.focused_child == nullptr || group.children.size() < 2) return; - auto& children = tab_node->data.as_group.children; + auto& children = group.children; if (target == TabFocus::Index) { int i = 1; @@ -1175,8 +1177,7 @@ hastab: return; cont:; } else { - auto node_iter = - std::find(children.begin(), children.end(), tab_node->data.as_group.focused_child); + auto node_iter = std::find(children.begin(), children.end(), group.focused_child); if (node_iter == children.end()) return; if (target == TabFocus::Left) { if (node_iter == children.begin()) { @@ -1197,9 +1198,9 @@ hastab: } auto* focus = tab_focused_node; - while (focus->data.type == Hy3NodeType::Group && !focus->data.as_group.group_focused - && focus->data.as_group.focused_child != nullptr) - focus = focus->data.as_group.focused_child; + while (focus->data.is_group() && !focus->data.as_group().group_focused + && focus->data.as_group().focused_child != nullptr) + focus = focus->data.as_group().focused_child; focus->focus(); tab_node->recalcSizePosRecursive(); @@ -1209,7 +1210,7 @@ void Hy3Layout::setNodeSwallow(const PHLWORKSPACE& workspace, SetSwallowOption o auto* node = this->getWorkspaceFocusedNode(workspace); if (node == nullptr || node->parent == nullptr) return; - auto* containment = &node->parent->data.as_group.containment; + auto* containment = &node->parent->data.as_group().containment; switch (option) { case SetSwallowOption::NoSwallow: *containment = false; break; case SetSwallowOption::Swallow: *containment = true; break; @@ -1218,16 +1219,17 @@ void Hy3Layout::setNodeSwallow(const PHLWORKSPACE& workspace, SetSwallowOption o } void Hy3Layout::killFocusedNode(const PHLWORKSPACE& workspace) { - if (g_pCompositor->m_pLastWindow != nullptr && g_pCompositor->m_pLastWindow->m_bIsFloating) { - g_pCompositor->closeWindow(g_pCompositor->m_pLastWindow); + auto last_window = g_pCompositor->m_pLastWindow.lock(); + if (last_window != nullptr && last_window->m_bIsFloating) { + g_pCompositor->closeWindow(last_window); } else { auto* node = this->getWorkspaceFocusedNode(workspace); if (node == nullptr) return; - std::vector windows; + std::vector windows; node->appendAllWindows(windows); - for (auto* window: windows) { + for (auto& window: windows) { window->setHidden(false); g_pCompositor->closeWindow(window); } @@ -1241,6 +1243,7 @@ void Hy3Layout::expand( ) { auto* node = this->getWorkspaceFocusedNode(workspace, false, true); if (node == nullptr) return; + PHLWINDOW window; const auto monitor = g_pCompositor->getMonitorFromID(workspace->m_iMonitorID); @@ -1254,10 +1257,10 @@ void Hy3Layout::expand( } } - if (node->data.type == Hy3NodeType::Group && !node->data.as_group.group_focused) - node->data.as_group.expand_focused = ExpandFocusType::Stack; + if (node->data.is_group() && !node->data.as_group().group_focused) + node->data.as_group().expand_focused = ExpandFocusType::Stack; - auto& group = node->parent->data.as_group; + auto& group = node->parent->data.as_group(); group.focused_child = node; group.expand_focused = ExpandFocusType::Latch; @@ -1272,19 +1275,19 @@ void Hy3Layout::expand( } } break; case ExpandOption::Shrink: - if (node->data.type == Hy3NodeType::Group) { - auto& group = node->data.as_group; + if (node->data.is_group()) { + auto& group = node->data.as_group(); group.expand_focused = ExpandFocusType::NotExpanded; - if (group.focused_child->data.type == Hy3NodeType::Group) - group.focused_child->data.as_group.expand_focused = ExpandFocusType::Latch; + if (group.focused_child->data.is_group()) + group.focused_child->data.as_group().expand_focused = ExpandFocusType::Latch; node->recalcSizePosRecursive(); } break; case ExpandOption::Base: { - if (node->data.type == Hy3NodeType::Group) { - node->data.as_group.collapseExpansions(); + if (node->data.is_group()) { + node->data.as_group().collapseExpansions(); node->recalcSizePosRecursive(); } break; @@ -1295,10 +1298,9 @@ void Hy3Layout::expand( return; - CWindow* window; fullscreen: - if (node->data.type != Hy3NodeType::Window) return; - window = node->data.as_window; + if (node->data.is_group()) return; + window = node->data.as_window(); if (!window->m_bIsFullscreen || window->m_pWorkspace->m_bIsSpecialWorkspace) return; if (workspace->m_bHasFullscreenWindow) return; @@ -1322,31 +1324,30 @@ fsupdate: this->recalculateMonitor(monitor->ID); } -bool Hy3Layout::shouldRenderSelected(CWindow* window) { +bool Hy3Layout::shouldRenderSelected(const PHLWINDOW& window) { if (window == nullptr) return false; auto* root = this->getWorkspaceRootGroup(window->m_pWorkspace); - if (root == nullptr || root->data.as_group.focused_child == nullptr) return false; + if (root == nullptr || root->data.as_group().focused_child == nullptr) return false; auto* focused = root->getFocusedNode(); if (focused == nullptr - || (focused->data.type == Hy3NodeType::Window - && focused->data.as_window != g_pCompositor->m_pLastWindow)) + || (focused->data.is_window() + && focused->data.as_window() != g_pCompositor->m_pLastWindow.lock())) return false; - switch (focused->data.type) { - case Hy3NodeType::Window: return focused->data.as_window == window; + switch (focused->data.type()) { + case Hy3NodeType::Window: return focused->data.as_window() == window; case Hy3NodeType::Group: { auto* node = this->getNodeFromWindow(window); if (node == nullptr) return false; - return focused->data.as_group.hasChild(node); + return focused->data.as_group().hasChild(node); } - default: return false; } } Hy3Node* Hy3Layout::getWorkspaceRootGroup(const PHLWORKSPACE& workspace) { for (auto& node: this->nodes) { - if (node.workspace == workspace && node.parent == nullptr - && node.data.type == Hy3NodeType::Group && !node.reparenting) + if (node.workspace == workspace && node.parent == nullptr && node.data.is_group() + && !node.reparenting) { return &node; } @@ -1380,7 +1381,7 @@ void Hy3Layout::renderHook(void*, SCallbackInfo&, std::any data) { if (!rendering_normally) break; for (auto& entry: g_Hy3Layout->tab_groups) { - if (!entry.hidden && entry.target_window == g_pHyprOpenGL->m_pCurrentWindow + if (!entry.hidden && entry.target_window == g_pHyprOpenGL->m_pCurrentWindow.lock() && std::find(rendered_groups.begin(), rendered_groups.end(), &entry) == rendered_groups.end()) { @@ -1409,18 +1410,17 @@ void Hy3Layout::renderHook(void*, SCallbackInfo&, std::any data) { } void Hy3Layout::windowGroupUrgentHook(void* p, SCallbackInfo& callback_info, std::any data) { - CWindow* window = std::any_cast(data); + auto window = std::any_cast(data); if (window == nullptr) return; window->m_bIsUrgent = true; Hy3Layout::windowGroupUpdateRecursiveHook(p, callback_info, data); } void Hy3Layout::windowGroupUpdateRecursiveHook(void*, SCallbackInfo&, std::any data) { - CWindow* window = std::any_cast(data); + auto window = std::any_cast(data); if (window == nullptr) return; auto* node = g_Hy3Layout->getNodeFromWindow(window); - // it is UB for `this` to be null if (node == nullptr) return; node->updateTabBarRecursive(); } @@ -1435,9 +1435,9 @@ void Hy3Layout::tickHook(void*, SCallbackInfo&, std::any) { } } -Hy3Node* Hy3Layout::getNodeFromWindow(CWindow* window) { +Hy3Node* Hy3Layout::getNodeFromWindow(const PHLWINDOW& window) { for (auto& node: this->nodes) { - if (node.data.type == Hy3NodeType::Window && node.data.as_window == window) { + if (node.data.is_window() && node.data.as_window() == window) { return &node; } } @@ -1446,8 +1446,8 @@ Hy3Node* Hy3Layout::getNodeFromWindow(CWindow* window) { } void Hy3Layout::applyNodeDataToWindow(Hy3Node* node, bool no_animation) { - if (node->data.type != Hy3NodeType::Window) return; - auto* window = node->data.as_window; + if (node->data.is_group()) return; + auto window = node->data.as_window(); auto root_node = this->getWorkspaceRootGroup(window->m_pWorkspace); CMonitor* monitor = nullptr; @@ -1480,13 +1480,13 @@ void Hy3Layout::applyNodeDataToWindow(Hy3Node* node, bool no_animation) { static const auto no_gaps_when_only = ConfigValue("plugin:hy3:no_gaps_when_only"); // clang-format on - if (!g_pCompositor->windowExists(window) || !window->m_bIsMapped) { + if (!valid(window) || !window->m_bIsMapped) { hy3_log( ERR, "node {:x} is an unmapped window ({:x}), cannot apply node data, removing from tiled " "layout", (uintptr_t) node, - (uintptr_t) window + (uintptr_t) window.get() ); errorNotif(); this->onWindowRemovedTiling(window); @@ -1501,8 +1501,8 @@ void Hy3Layout::applyNodeDataToWindow(Hy3Node* node, bool no_animation) { window->m_vSize = nodeBox.size(); window->m_vPosition = nodeBox.pos(); - auto only_node = root_node != nullptr && root_node->data.as_group.children.size() == 1 - && root_node->data.as_group.children.front()->data.type == Hy3NodeType::Window; + auto only_node = root_node != nullptr && root_node->data.as_group().children.size() == 1 + && root_node->data.as_group().children.front()->data.is_window(); if (!window->m_pWorkspace->m_bIsSpecialWorkspace && ((*no_gaps_when_only != 0 && (only_node || window->m_bIsFullscreen)) @@ -1589,7 +1589,7 @@ Hy3Node* Hy3Layout::shiftOrGetFocus( while (true) { if (break_parent == nullptr) return nullptr; - auto& group = break_parent->data.as_group; // must be a group in order to be a parent + auto& group = break_parent->data.as_group(); // must be a group in order to be a parent if (shiftMatchesLayout(group.layout, direction) && (!visible || group.layout != Hy3GroupLayout::Tabbed)) @@ -1636,9 +1636,10 @@ Hy3Node* Hy3Layout::shiftOrGetFocus( auto* newChild = &this->nodes.back(); Hy3Node::swapData(*break_parent, *newChild); - break_parent->data.as_group.children.push_back(newChild); - break_parent->data.as_group.group_focused = false; - break_parent->data.as_group.focused_child = newChild; + auto& group = break_parent->data.as_group(); + group.children.push_back(newChild); + group.group_focused = false; + group.focused_child = newChild; break_origin = newChild; } @@ -1649,7 +1650,7 @@ Hy3Node* Hy3Layout::shiftOrGetFocus( } } - auto& parent_group = break_parent->data.as_group; + auto& parent_group = break_parent->data.as_group(); Hy3Node* target_group = break_parent; std::list::iterator insert; @@ -1660,15 +1661,15 @@ Hy3Node* Hy3Layout::shiftOrGetFocus( if (!shift) return nullptr; insert = parent_group.children.end(); } else { - auto& group_data = target_group->data.as_group; + auto& group_data = target_group->data.as_group(); auto iter = std::find(group_data.children.begin(), group_data.children.end(), break_origin); if (shiftIsForward(direction)) iter = std::next(iter); else iter = std::prev(iter); - if ((*iter)->data.type == Hy3NodeType::Window - || ((*iter)->data.type == Hy3NodeType::Group - && (*iter)->data.as_group.expand_focused != ExpandFocusType::NotExpanded) + if ((*iter)->data.is_window() + || ((*iter)->data.is_group() + && (*iter)->data.as_group().expand_focused != ExpandFocusType::NotExpanded) || (shift && once && has_broken_once)) { if (shift) { @@ -1684,7 +1685,7 @@ Hy3Node* Hy3Layout::shiftOrGetFocus( // break into neighboring groups until we hit a window while (true) { target_group = *iter; - auto& group_data = target_group->data.as_group; + auto& group_data = target_group->data.as_group(); if (group_data.children.empty()) return nullptr; // in theory this would never happen @@ -1735,9 +1736,9 @@ Hy3Node* Hy3Layout::shiftOrGetFocus( break; } - if ((*iter)->data.type == Hy3NodeType::Window - || ((*iter)->data.type == Hy3NodeType::Group - && (*iter)->data.as_group.expand_focused != ExpandFocusType::NotExpanded)) + if ((*iter)->data.is_window() + || ((*iter)->data.is_group() + && (*iter)->data.as_group().expand_focused != ExpandFocusType::NotExpanded)) { if (shift) { if (shift_after) insert = std::next(iter); @@ -1751,18 +1752,19 @@ Hy3Node* Hy3Layout::shiftOrGetFocus( } } - auto& group_data = target_group->data.as_group; + auto& group_data = target_group->data.as_group(); if (target_group == node.parent) { // nullptr is used as a signal value instead of removing it first to avoid // iterator invalidation. auto iter = std::find(group_data.children.begin(), group_data.children.end(), &node); *iter = nullptr; - target_group->data.as_group.children.insert(insert, &node); - target_group->data.as_group.children.remove(nullptr); + auto& group = target_group->data.as_group(); + group.children.insert(insert, &node); + group.children.remove(nullptr); target_group->recalcSizePosRecursive(); } else { - target_group->data.as_group.children.insert(insert, &node); + target_group->data.as_group().children.insert(insert, &node); // must happen AFTER `insert` is used auto* old_parent = node.removeFromParentRecursive(nullptr); @@ -1770,7 +1772,7 @@ Hy3Node* Hy3Layout::shiftOrGetFocus( node.size_ratio = 1.0; if (old_parent != nullptr) { - auto& group = old_parent->data.as_group; + auto& group = old_parent->data.as_group(); if (old_parent->parent != nullptr && group.ephemeral && group.children.size() == 1 && !group.hasChild(&node)) { diff --git a/src/Hy3Layout.hpp b/src/Hy3Layout.hpp index 3bb27de..7916261 100644 --- a/src/Hy3Layout.hpp +++ b/src/Hy3Layout.hpp @@ -70,30 +70,30 @@ enum class ExpandFullscreenOption { class Hy3Layout: public IHyprLayout { public: - virtual void onWindowCreated(CWindow*, eDirection = DIRECTION_DEFAULT); - virtual void onWindowCreatedTiling(CWindow*, eDirection = DIRECTION_DEFAULT); - virtual void onWindowRemovedTiling(CWindow*); - virtual void onWindowFocusChange(CWindow*); - virtual bool isWindowTiled(CWindow*); - virtual void recalculateMonitor(const int& monitor_id); - virtual void recalculateWindow(CWindow*); - virtual void - resizeActiveWindow(const Vector2D& delta, eRectCorner corner, CWindow* pWindow = nullptr); - virtual void fullscreenRequestForWindow(CWindow*, eFullscreenMode, bool enable_fullscreen); - virtual std::any layoutMessage(SLayoutMessageHeader header, std::string content); - virtual SWindowRenderLayoutHints requestRenderHints(CWindow*); - virtual void switchWindows(CWindow*, CWindow*); - virtual void moveWindowTo(CWindow*, const std::string& direction, bool silent); - virtual void alterSplitRatio(CWindow*, float, bool); - virtual std::string getLayoutName(); - virtual CWindow* getNextWindowCandidate(CWindow*); - virtual void replaceWindowDataWith(CWindow* from, CWindow* to); - virtual bool isWindowReachable(CWindow*); - virtual void bringWindowToTop(CWindow*); - virtual Vector2D predictSizeForNewWindowTiled() { return Vector2D(); } + void onWindowCreated(PHLWINDOW, eDirection = DIRECTION_DEFAULT) override; + void onWindowCreatedTiling(PHLWINDOW, eDirection = DIRECTION_DEFAULT) override; + void onWindowRemovedTiling(PHLWINDOW) override; + void onWindowFocusChange(PHLWINDOW) override; + bool isWindowTiled(PHLWINDOW) override; + void recalculateMonitor(const int& monitor_id) override; + void recalculateWindow(PHLWINDOW) override; + void resizeActiveWindow(const Vector2D& delta, eRectCorner corner, PHLWINDOW pWindow = nullptr) + override; + void fullscreenRequestForWindow(PHLWINDOW, eFullscreenMode, bool enable_fullscreen) override; + std::any layoutMessage(SLayoutMessageHeader header, std::string content) override; + SWindowRenderLayoutHints requestRenderHints(PHLWINDOW) override; + void switchWindows(PHLWINDOW, PHLWINDOW) override; + void moveWindowTo(PHLWINDOW, const std::string& direction, bool silent) override; + void alterSplitRatio(PHLWINDOW, float, bool) override; + std::string getLayoutName() override; + PHLWINDOW getNextWindowCandidate(PHLWINDOW) override; + void replaceWindowDataWith(PHLWINDOW from, PHLWINDOW to) override; + bool isWindowReachable(PHLWINDOW) override; + void bringWindowToTop(PHLWINDOW) override; + Vector2D predictSizeForNewWindowTiled() override { return Vector2D(); } - virtual void onEnable(); - virtual void onDisable(); + void onEnable() override; + void onDisable() override; void insertNode(Hy3Node& node); void makeGroupOnWorkspace(const PHLWORKSPACE& workspace, Hy3GroupLayout, GroupEphemeralityOption); @@ -126,7 +126,7 @@ public: void killFocusedNode(const PHLWORKSPACE& workspace); void expand(const PHLWORKSPACE& workspace, ExpandOption, ExpandFullscreenOption); - bool shouldRenderSelected(CWindow*); + bool shouldRenderSelected(const PHLWINDOW&); Hy3Node* getWorkspaceRootGroup(const PHLWORKSPACE& workspace); Hy3Node* getWorkspaceFocusedNode( @@ -144,7 +144,7 @@ public: std::list tab_groups; private: - Hy3Node* getNodeFromWindow(CWindow*); + Hy3Node* getNodeFromWindow(const PHLWINDOW&); void applyNodeDataToWindow(Hy3Node*, bool no_animation = false); // if shift is true, shift the window in the given direction, returning diff --git a/src/Hy3Node.cpp b/src/Hy3Node.cpp index 9572d7b..04ef6f5 100644 --- a/src/Hy3Node.cpp +++ b/src/Hy3Node.cpp @@ -1,6 +1,10 @@ #include +#include +#include +#include #include +#include #include #include @@ -37,8 +41,8 @@ bool Hy3GroupData::hasChild(Hy3Node* node) { for (auto child: this->children) { if (child == node) return true; - if (child->data.type == Hy3NodeType::Group) { - if (child->data.as_group.hasChild(node)) return true; + if (child->data.is_group()) { + if (child->data.as_group().hasChild(node)) return true; } } @@ -51,11 +55,10 @@ void Hy3GroupData::collapseExpansions() { Hy3Node* node = this->focused_child; - while (node->data.type == Hy3NodeType::Group - && node->data.as_group.expand_focused == ExpandFocusType::Stack) - { - node->data.as_group.expand_focused = ExpandFocusType::NotExpanded; - node = node->data.as_group.focused_child; + while (node->data.is_group() && node->data.as_group().expand_focused == ExpandFocusType::Stack) { + auto& group = node->data.as_group(); + group.expand_focused = ExpandFocusType::NotExpanded; + node = group.focused_child; } } @@ -79,64 +82,83 @@ void Hy3GroupData::setEphemeral(GroupEphemeralityOption ephemeral) { // Hy3NodeData // -Hy3NodeData::Hy3NodeData(): Hy3NodeData((CWindow*) nullptr) {} +Hy3NodeData::Hy3NodeData(Hy3GroupLayout layout) { this->data.emplace<1>(layout); } -Hy3NodeData::Hy3NodeData(CWindow* window): type(Hy3NodeType::Window) { this->as_window = window; } +Hy3NodeData::Hy3NodeData(PHLWINDOW window) { this->data.emplace<0>(window); } -Hy3NodeData::Hy3NodeData(Hy3GroupLayout layout): Hy3NodeData(Hy3GroupData(layout)) {} +Hy3NodeData::Hy3NodeData(Hy3GroupData group) { this->data.emplace<1>(std::move(group)); } -Hy3NodeData::Hy3NodeData(Hy3GroupData group): type(Hy3NodeType::Group) { - new (&this->as_group) Hy3GroupData(std::move(group)); -} - -Hy3NodeData::Hy3NodeData(Hy3NodeData&& from): type(from.type) { - switch (from.type) { - case Hy3NodeType::Window: this->as_window = from.as_window; break; - case Hy3NodeType::Group: new (&this->as_group) Hy3GroupData(std::move(from.as_group)); break; +Hy3NodeData::Hy3NodeData(Hy3NodeData&& node) { + if (std::holds_alternative(node.data)) { + this->data.emplace<0>(std::get(node.data)); + } else if (std::holds_alternative(node.data)) { + this->data.emplace<1>(std::move(std::get(node.data))); } } -Hy3NodeData::~Hy3NodeData() { - switch (this->type) { - case Hy3NodeType::Window: break; - case Hy3NodeType::Group: - this->as_group.~Hy3GroupData(); - - // who ever thought calling the dtor after a move was a good idea? - this->type = Hy3NodeType::Window; - break; - } -} - -Hy3NodeData& Hy3NodeData::operator=(CWindow* window) { +Hy3NodeData& Hy3NodeData::operator=(PHLWINDOW window) { *this = Hy3NodeData(window); - return *this; } Hy3NodeData& Hy3NodeData::operator=(Hy3GroupLayout layout) { *this = Hy3NodeData(layout); - return *this; } Hy3NodeData& Hy3NodeData::operator=(Hy3NodeData&& from) { - if (this->type == Hy3NodeType::Group) { - this->as_group.~Hy3GroupData(); - } - - this->type = from.type; - - switch (this->type) { - case Hy3NodeType::Window: this->as_window = from.as_window; break; - case Hy3NodeType::Group: new (&this->as_group) Hy3GroupData(std::move(from.as_group)); break; - } - + this->~Hy3NodeData(); + new (this) Hy3NodeData(std::move(from)); return *this; } bool Hy3NodeData::operator==(const Hy3NodeData& rhs) const { return this == &rhs; } +bool Hy3NodeData::valid() const { + if (std::holds_alternative(this->data)) { + return true; + } else if (std::holds_alternative(this->data)) { + return !std::get(this->data).expired(); + } else { + return false; + } +} + +Hy3NodeType Hy3NodeData::type() const { + if (std::holds_alternative(this->data)) { + return Hy3NodeType::Group; + } else if (std::holds_alternative(this->data)) { + return Hy3NodeType::Window; + } else { + throw std::runtime_error("Attempted to get Hy3NodeType of uninitialized Hy3NodeData"); + } +} + +bool Hy3NodeData::is_group() const { return this->type() == Hy3NodeType::Group; } + +bool Hy3NodeData::is_window() const { return this->type() == Hy3NodeType::Window; } + +Hy3GroupData& Hy3NodeData::as_group() { + if (std::holds_alternative(this->data)) { + return std::get(this->data); + } else { + throw std::runtime_error("Attempted to get group value of a non-group Hy3NodeData"); + } +} + +PHLWINDOW Hy3NodeData::as_window() { + if (std::holds_alternative(this->data)) { + auto& ref = std::get(this->data); + if (ref.expired()) { + throw std::runtime_error("Attempted to upgrade an expired Hy3NodeData of a window"); + } else { + return ref.lock(); + } + } else { + throw std::runtime_error("Attempted to get window value of a non-window Hy3NodeData"); + } +} + // Hy3Node // bool Hy3Node::operator==(const Hy3Node& rhs) const { return this->data == rhs.data; } @@ -144,10 +166,10 @@ bool Hy3Node::operator==(const Hy3Node& rhs) const { return this->data == rhs.da void Hy3Node::focus() { this->markFocused(); - switch (this->data.type) { + switch (this->data.type()) { case Hy3NodeType::Window: - this->data.as_window->setHidden(false); - g_pCompositor->focusWindow(this->data.as_window); + this->data.as_window()->setHidden(false); + g_pCompositor->focusWindow(this->data.as_window()); break; case Hy3NodeType::Group: g_pCompositor->focusWindow(nullptr); @@ -156,39 +178,41 @@ void Hy3Node::focus() { } } -CWindow* Hy3Node::bringToTop() { - switch (this->data.type) { - case Hy3NodeType::Window: +PHLWINDOW Hy3Node::bringToTop() { + switch (this->data.type()) { + case Hy3NodeType::Window: { this->markFocused(); - this->data.as_window->setHidden(false); - - return this->data.as_window; - case Hy3NodeType::Group: - if (this->data.as_group.layout == Hy3GroupLayout::Tabbed) { - if (this->data.as_group.focused_child != nullptr) { - return this->data.as_group.focused_child->bringToTop(); + auto window = this->data.as_window(); + window->setHidden(false); + return window; + } + case Hy3NodeType::Group: { + auto& group = this->data.as_group(); + if (group.layout == Hy3GroupLayout::Tabbed) { + if (group.focused_child != nullptr) { + return group.focused_child->bringToTop(); } } else { - for (auto* node: this->data.as_group.children) { - auto* window = node->bringToTop(); + for (auto* node: group.children) { + auto window = node->bringToTop(); if (window != nullptr) return window; } } return nullptr; - default: return nullptr; + } } } void Hy3Node::focusWindow() { - auto* window = this->bringToTop(); + auto window = this->bringToTop(); if (window != nullptr) g_pCompositor->focusWindow(window); } void markGroupFocusedRecursive(Hy3GroupData& group) { group.group_focused = true; for (auto& child: group.children) { - if (child->data.type == Hy3NodeType::Group) markGroupFocusedRecursive(child->data.as_group); + if (child->data.is_group()) markGroupFocusedRecursive(child->data.as_group()); } } @@ -200,14 +224,15 @@ void Hy3Node::markFocused() { while (root->parent != nullptr) root = root->parent; // update focus - if (this->data.type == Hy3NodeType::Group) { - markGroupFocusedRecursive(this->data.as_group); + if (this->data.is_group()) { + markGroupFocusedRecursive(this->data.as_group()); } auto* node2 = node; while (node2->parent != nullptr) { - node2->parent->data.as_group.focused_child = node2; - node2->parent->data.as_group.group_focused = false; + auto& group = node2->parent->data.as_group(); + group.focused_child = node2; + group.group_focused = false; node2 = node2->parent; } @@ -215,10 +240,10 @@ void Hy3Node::markFocused() { } void Hy3Node::raiseToTop() { - switch (this->data.type) { - case Hy3NodeType::Window: g_pCompositor->changeWindowZOrder(this->data.as_window, true); break; + switch (this->data.type()) { + case Hy3NodeType::Window: g_pCompositor->changeWindowZOrder(this->data.as_window(), true); break; case Hy3NodeType::Group: - for (auto* child: this->data.as_group.children) { + for (auto* child: this->data.as_group().children) { child->raiseToTop(); } break; @@ -226,21 +251,19 @@ void Hy3Node::raiseToTop() { } Hy3Node* Hy3Node::getFocusedNode(bool ignore_group_focus, bool stop_at_expanded) { - switch (this->data.type) { + switch (this->data.type()) { case Hy3NodeType::Window: return this; - case Hy3NodeType::Group: - if (this->data.as_group.focused_child == nullptr - || (!ignore_group_focus && this->data.as_group.group_focused) - || (stop_at_expanded && this->data.as_group.expand_focused != ExpandFocusType::NotExpanded)) + case Hy3NodeType::Group: { + auto& group = this->data.as_group(); + + if (group.focused_child == nullptr || (!ignore_group_focus && group.group_focused) + || (stop_at_expanded && group.expand_focused != ExpandFocusType::NotExpanded)) { return this; } else { - return this->data.as_group.focused_child->getFocusedNode( - ignore_group_focus, - stop_at_expanded - ); + return group.focused_child->getFocusedNode(ignore_group_focus, stop_at_expanded); } - default: return nullptr; + } } } @@ -248,9 +271,8 @@ bool Hy3Node::isIndirectlyFocused() { Hy3Node* node = this; while (node->parent != nullptr) { - if (!node->parent->data.as_group.group_focused - && node->parent->data.as_group.focused_child != node) - return false; + auto& group = node->parent->data.as_group(); + if (!group.group_focused && group.focused_child != node) return false; node = node->parent; } @@ -262,7 +284,7 @@ Hy3Node& Hy3Node::getExpandActor() { Hy3Node* node = this; while (node->parent != nullptr - && node->parent->data.as_group.expand_focused != ExpandFocusType::NotExpanded) + && node->parent->data.as_group().expand_focused != ExpandFocusType::NotExpanded) node = node->parent; return *node; @@ -289,17 +311,18 @@ void Hy3Node::recalcSizePosRecursive(bool no_animation) { ); // clang-format on - if (this->data.type == Hy3NodeType::Window && this->data.as_window->m_bIsFullscreen) { + if (this->data.is_window() && this->data.as_window()->m_bIsFullscreen) { + auto window = this->data.as_window(); auto* monitor = g_pCompositor->getMonitorFromID(this->workspace->m_iMonitorID); if (this->workspace->m_efFullscreenMode == FULLSCREEN_FULL) { - this->data.as_window->m_vRealPosition = monitor->vecPosition; - this->data.as_window->m_vRealSize = monitor->vecSize; + window->m_vRealPosition = monitor->vecPosition; + window->m_vRealSize = monitor->vecSize; return; } Hy3Node fake_node = { - .data = this->data.as_window, + .data = window, .position = monitor->vecPosition + monitor->vecReservedTopLeft, .size = monitor->vecSize - monitor->vecReservedTopLeft - monitor->vecReservedBottomRight, .gap_topleft_offset = gap_topleft_offset, @@ -321,16 +344,16 @@ void Hy3Node::recalcSizePosRecursive(bool no_animation) { double tab_height_offset = *tab_bar_height + *tab_bar_padding; - if (this->data.type == Hy3NodeType::Window) { - this->data.as_window->setHidden(this->hidden); + if (this->data.is_window()) { + this->data.as_window()->setHidden(this->hidden); this->layout->applyNodeDataToWindow(this, no_animation); return; } - auto* group = &this->data.as_group; + auto& group = this->data.as_group(); double constraint; - switch (group->layout) { + switch (group.layout) { case Hy3GroupLayout::SplitH: constraint = tsize.x - gap_topleft_offset.x - gap_bottomright_offset.x; break; @@ -340,34 +363,34 @@ void Hy3Node::recalcSizePosRecursive(bool no_animation) { case Hy3GroupLayout::Tabbed: break; } - auto expand_focused = group->expand_focused != ExpandFocusType::NotExpanded; + auto expand_focused = group.expand_focused != ExpandFocusType::NotExpanded; bool directly_contains_expanded = expand_focused - && (group->focused_child->data.type == Hy3NodeType::Window - || group->focused_child->data.as_group.expand_focused == ExpandFocusType::NotExpanded); + && (group.focused_child->data.is_window() + || group.focused_child->data.as_group().expand_focused == ExpandFocusType::NotExpanded); - auto child_count = group->children.size(); + auto child_count = group.children.size(); double ratio_mul = - group->layout != Hy3GroupLayout::Tabbed ? child_count <= 0 ? 0 : constraint / child_count : 0; + group.layout != Hy3GroupLayout::Tabbed ? child_count <= 0 ? 0 : constraint / child_count : 0; double offset = 0; - if (group->layout == Hy3GroupLayout::Tabbed && group->focused_child != nullptr - && !group->focused_child->hidden) + if (group.layout == Hy3GroupLayout::Tabbed && group.focused_child != nullptr + && !group.focused_child->hidden) { - group->focused_child->setHidden(false); + group.focused_child->setHidden(false); auto box = CBox {tpos.x, tpos.y, tsize.x, tsize.y}; g_pHyprRenderer->damageBox(&box); } - if (group->expand_focused == ExpandFocusType::Latch) { - auto* expanded_node = group->focused_child; + if (group.expand_focused == ExpandFocusType::Latch) { + auto* expanded_node = group.focused_child; - while (expanded_node != nullptr && expanded_node->data.type == Hy3NodeType::Group - && expanded_node->data.as_group.expand_focused != ExpandFocusType::NotExpanded) + while (expanded_node != nullptr && expanded_node->data.is_group() + && expanded_node->data.as_group().expand_focused != ExpandFocusType::NotExpanded) { - expanded_node = expanded_node->data.as_group.focused_child; + expanded_node = expanded_node->data.as_group().focused_child; } if (expanded_node == nullptr) { @@ -390,9 +413,9 @@ void Hy3Node::recalcSizePosRecursive(bool no_animation) { expanded_node->recalcSizePosRecursive(no_animation); } - for (auto* child: group->children) { - if (directly_contains_expanded && child == group->focused_child) { - switch (group->layout) { + for (auto* child: group.children) { + if (directly_contains_expanded && child == group.focused_child) { + switch (group.layout) { case Hy3GroupLayout::SplitH: offset += child->size_ratio * ratio_mul; break; case Hy3GroupLayout::SplitV: offset += child->size_ratio * ratio_mul; break; case Hy3GroupLayout::Tabbed: break; @@ -401,7 +424,7 @@ void Hy3Node::recalcSizePosRecursive(bool no_animation) { continue; } - switch (group->layout) { + switch (group.layout) { case Hy3GroupLayout::SplitH: child->position.x = tpos.x + offset; child->size.x = child->size_ratio * ratio_mul; @@ -410,17 +433,17 @@ void Hy3Node::recalcSizePosRecursive(bool no_animation) { child->size.y = tsize.y; child->hidden = this->hidden || expand_focused; - if (group->children.size() == 1) { + if (group.children.size() == 1) { child->gap_topleft_offset = gap_topleft_offset; child->gap_bottomright_offset = gap_bottomright_offset; child->size.x = tsize.x; if (this->parent != nullptr) child->gap_bottomright_offset.x += *group_inset; - } else if (child == group->children.front()) { + } else if (child == group.children.front()) { child->gap_topleft_offset = gap_topleft_offset; child->gap_bottomright_offset = Vector2D(0, gap_bottomright_offset.y); child->size.x += gap_topleft_offset.x; offset += gap_topleft_offset.x; - } else if (child == group->children.back()) { + } else if (child == group.children.back()) { child->gap_topleft_offset = Vector2D(0, gap_topleft_offset.y); child->gap_bottomright_offset = gap_bottomright_offset; child->size.x += gap_bottomright_offset.x; @@ -439,17 +462,17 @@ void Hy3Node::recalcSizePosRecursive(bool no_animation) { child->size.x = tsize.x; child->hidden = this->hidden || expand_focused; - if (group->children.size() == 1) { + if (group.children.size() == 1) { child->gap_topleft_offset = gap_topleft_offset; child->gap_bottomright_offset = gap_bottomright_offset; child->size.y = tsize.y; if (this->parent != nullptr) child->gap_bottomright_offset.y += *group_inset; - } else if (child == group->children.front()) { + } else if (child == group.children.front()) { child->gap_topleft_offset = gap_topleft_offset; child->gap_bottomright_offset = Vector2D(gap_bottomright_offset.x, 0); child->size.y += gap_topleft_offset.y; offset += gap_topleft_offset.y; - } else if (child == group->children.back()) { + } else if (child == group.children.back()) { child->gap_topleft_offset = Vector2D(gap_topleft_offset.x, 0); child->gap_bottomright_offset = gap_bottomright_offset; child->size.y += gap_bottomright_offset.y; @@ -463,7 +486,7 @@ void Hy3Node::recalcSizePosRecursive(bool no_animation) { case Hy3GroupLayout::Tabbed: child->position = tpos; child->size = tsize; - child->hidden = this->hidden || expand_focused || group->focused_child != child; + child->hidden = this->hidden || expand_focused || group.focused_child != child; child->gap_topleft_offset = Vector2D(gap_topleft_offset.x, gap_topleft_offset.y + tab_height_offset); @@ -478,18 +501,18 @@ void Hy3Node::recalcSizePosRecursive(bool no_animation) { } struct FindTopWindowInNodeResult { - CWindow* window = nullptr; + PHLWINDOW window = nullptr; size_t index = 0; }; void findTopWindowInNode(Hy3Node& node, FindTopWindowInNodeResult& result) { - switch (node.data.type) { + switch (node.data.type()) { case Hy3NodeType::Window: { - auto* window = node.data.as_window; + auto window = node.data.as_window(); auto& windows = g_pCompositor->m_vWindows; for (; result.index < windows.size(); result.index++) { - if (&*windows[result.index] == window) { + if (windows[result.index] == window) { result.window = window; break; } @@ -497,7 +520,7 @@ void findTopWindowInNode(Hy3Node& node, FindTopWindowInNodeResult& result) { } break; case Hy3NodeType::Group: { - auto& group = node.data.as_group; + auto& group = node.data.as_group(); if (group.layout == Hy3GroupLayout::Tabbed) { if (group.focused_child != nullptr) findTopWindowInNode(*group.focused_child, result); @@ -511,8 +534,8 @@ void findTopWindowInNode(Hy3Node& node, FindTopWindowInNodeResult& result) { } void Hy3Node::updateTabBar(bool no_animation) { - if (this->data.type == Hy3NodeType::Group) { - auto& group = this->data.as_group; + if (this->data.type() == Hy3NodeType::Group) { + auto& group = this->data.as_group(); if (group.layout == Hy3GroupLayout::Tabbed) { if (group.tab_bar == nullptr) group.tab_bar = &this->layout->tab_groups.emplace_back(*this); @@ -539,13 +562,12 @@ void Hy3Node::updateTabBarRecursive() { } void Hy3Node::updateDecos() { - switch (this->data.type) { + switch (this->data.type()) { case Hy3NodeType::Window: - if (this->data.as_window->m_bIsMapped) - g_pCompositor->updateWindowAnimatedDecorationValues(this->data.as_window); + g_pCompositor->updateWindowAnimatedDecorationValues(this->data.as_window()); break; case Hy3NodeType::Group: - for (auto* child: this->data.as_group.children) { + for (auto* child: this->data.as_group().children) { child->updateDecos(); } @@ -554,21 +576,22 @@ void Hy3Node::updateDecos() { } std::string Hy3Node::getTitle() { - switch (this->data.type) { - case Hy3NodeType::Window: return this->data.as_window->m_szTitle; + switch (this->data.type()) { + case Hy3NodeType::Window: return this->data.as_window()->m_szTitle; case Hy3NodeType::Group: std::string title; + auto& group = this->data.as_group(); - switch (this->data.as_group.layout) { + switch (group.layout) { case Hy3GroupLayout::SplitH: title = "[H] "; break; case Hy3GroupLayout::SplitV: title = "[V] "; break; case Hy3GroupLayout::Tabbed: title = "[T] "; break; } - if (this->data.as_group.focused_child == nullptr) { + if (group.focused_child == nullptr) { title += "Group"; } else { - title += this->data.as_group.focused_child->getTitle(); + title += group.focused_child->getTitle(); } return title; @@ -578,33 +601,31 @@ std::string Hy3Node::getTitle() { } bool Hy3Node::isUrgent() { - switch (this->data.type) { - case Hy3NodeType::Window: return this->data.as_window->m_bIsUrgent; + switch (this->data.type()) { + case Hy3NodeType::Window: return this->data.as_window()->m_bIsUrgent; case Hy3NodeType::Group: - for (auto* child: this->data.as_group.children) { + for (auto* child: this->data.as_group().children) { if (child->isUrgent()) return true; } return false; - default: return false; } } void Hy3Node::setHidden(bool hidden) { this->hidden = hidden; - if (this->data.type == Hy3NodeType::Group) { - for (auto* child: this->data.as_group.children) { + if (this->data.is_group()) { + for (auto* child: this->data.as_group().children) { child->setHidden(hidden); } } } Hy3Node* Hy3Node::findNodeForTabGroup(Hy3TabGroup& tab_group) { - if (this->data.type == Hy3NodeType::Group) { + if (this->data.is_group()) { if (this->hidden) return nullptr; - - auto& group = this->data.as_group; + auto& group = this->data.as_group(); if (group.layout == Hy3GroupLayout::Tabbed && group.tab_bar == &tab_group) { return this; @@ -619,11 +640,11 @@ Hy3Node* Hy3Node::findNodeForTabGroup(Hy3TabGroup& tab_group) { return nullptr; } -void Hy3Node::appendAllWindows(std::vector& list) { - switch (this->data.type) { - case Hy3NodeType::Window: list.push_back(this->data.as_window); break; +void Hy3Node::appendAllWindows(std::vector& list) { + switch (this->data.type()) { + case Hy3NodeType::Window: list.push_back(this->data.as_window()); break; case Hy3NodeType::Group: - for (auto* child: this->data.as_group.children) { + for (auto* child: this->data.as_group().children) { child->appendAllWindows(list); } break; @@ -633,12 +654,12 @@ void Hy3Node::appendAllWindows(std::vector& list) { std::string Hy3Node::debugNode() { std::stringstream buf; std::string addr = "0x" + std::to_string((size_t) this); - switch (this->data.type) { + switch (this->data.type()) { case Hy3NodeType::Window: buf << "window("; buf << std::hex << this; buf << ") [hypr "; - buf << this->data.as_window; + buf << this->data.as_window(); buf << "] size ratio: "; buf << this->size_ratio; break; @@ -647,7 +668,8 @@ std::string Hy3Node::debugNode() { buf << std::hex << this; buf << ") ["; - switch (this->data.as_group.layout) { + auto& group = this->data.as_group(); + switch (group.layout) { case Hy3GroupLayout::SplitH: buf << "splith"; break; case Hy3GroupLayout::SplitV: buf << "splitv"; break; case Hy3GroupLayout::Tabbed: buf << "tabs"; break; @@ -656,19 +678,19 @@ std::string Hy3Node::debugNode() { buf << "] size ratio: "; buf << this->size_ratio; - if (this->data.as_group.expand_focused != ExpandFocusType::NotExpanded) { + if (group.expand_focused != ExpandFocusType::NotExpanded) { buf << ", has-expanded"; } - if (this->data.as_group.ephemeral) { + if (group.ephemeral) { buf << ", ephemeral"; } - if (this->data.as_group.containment) { + if (group.containment) { buf << ", containment"; } - for (auto* child: this->data.as_group.children) { + for (auto* child: group.children) { buf << "\n|-"; if (child == nullptr) { buf << "nullptr"; @@ -694,8 +716,8 @@ Hy3Node* Hy3Node::removeFromParentRecursive(Hy3Node** expand_actor) { if (this->parent != nullptr) { auto& actor = this->getExpandActor(); - if (actor.data.type == Hy3NodeType::Group) { - actor.data.as_group.collapseExpansions(); + if (actor.data.is_group()) { + actor.data.as_group().collapseExpansions(); if (expand_actor != nullptr) *expand_actor = &actor; } } @@ -708,7 +730,7 @@ Hy3Node* Hy3Node::removeFromParentRecursive(Hy3Node** expand_actor) { auto* child = parent; parent = parent->parent; - auto& group = parent->data.as_group; + auto& group = parent->data.as_group(); if (group.children.size() > 2) { auto iter = std::find(group.children.begin(), group.children.end(), child); @@ -778,11 +800,12 @@ Hy3Node* Hy3Node::intoGroup(Hy3GroupLayout layout, GroupEphemeralityOption ephem swapData(*this, *node); this->data = layout; - this->data.as_group.children.push_back(node); - this->data.as_group.group_focused = false; - this->data.as_group.focused_child = node; - this->data.as_group.ephemeral = ephemeral == GroupEphemeralityOption::Ephemeral - || ephemeral == GroupEphemeralityOption::ForceEphemeral; + auto& group = this->data.as_group(); + group.children.push_back(node); + group.group_focused = false; + group.focused_child = node; + group.ephemeral = ephemeral == GroupEphemeralityOption::Ephemeral + || ephemeral == GroupEphemeralityOption::ForceEphemeral; this->recalcSizePosRecursive(); this->updateTabBarRecursive(); @@ -790,15 +813,14 @@ Hy3Node* Hy3Node::intoGroup(Hy3GroupLayout layout, GroupEphemeralityOption ephem } bool Hy3Node::swallowGroups(Hy3Node* into) { - if (into == nullptr || into->data.type != Hy3NodeType::Group - || into->data.as_group.children.size() != 1) + if (into == nullptr || into->data.is_window() || into->data.as_group().children.size() != 1) return false; - auto* child = into->data.as_group.children.front(); + auto* child = into->data.as_group().children.front(); // a lot of segfaulting happens once the assumption that the root node is a // group is wrong. - if (into->parent == nullptr && child->data.type != Hy3NodeType::Group) return false; + if (into->parent == nullptr && child->data.is_window()) return false; hy3_log(TRACE, "swallowing node {:x} into node {:x}", (uintptr_t) child, (uintptr_t) into); @@ -819,7 +841,7 @@ Hy3Node* getOuterChild(Hy3GroupData& group, ShiftDirection direction) { } Hy3Node* Hy3Node::getImmediateSibling(ShiftDirection direction) { - const auto& group = this->parent->data.as_group; + const auto& group = this->parent->data.as_group(); auto iter = std::find(group.children.begin(), group.children.end(), this); @@ -864,7 +886,7 @@ Hy3Node* Hy3Node::findNeighbor(ShiftDirection direction) { Hy3Node* sibling = nullptr; while (sibling == nullptr && current_node->parent != nullptr) { - auto& parent_group = current_node->parent->data.as_group; + auto& parent_group = current_node->parent->data.as_group(); if (parent_group.layout != Hy3GroupLayout::Tabbed && getAxis(parent_group.layout) == getAxis(direction)) @@ -895,7 +917,7 @@ int directionToIteratorIncrement(ShiftDirection direction) { void Hy3Node::resize(ShiftDirection direction, double delta, bool no_animation) { auto& parent_node = this->parent; - auto& containing_group = parent_node->data.as_group; + auto& containing_group = parent_node->data.as_group(); if (containing_group.layout != Hy3GroupLayout::Tabbed && getAxis(direction) == getAxis(containing_group.layout)) @@ -936,14 +958,14 @@ void Hy3Node::swapData(Hy3Node& a, Hy3Node& b) { a.data = std::move(b.data); b.data = std::move(aData); - if (a.data.type == Hy3NodeType::Group) { - for (auto child: a.data.as_group.children) { + if (a.data.is_group()) { + for (auto child: a.data.as_group().children) { child->parent = &a; } } - if (b.data.type == Hy3NodeType::Group) { - for (auto child: b.data.as_group.children) { + if (b.data.is_group()) { + for (auto child: b.data.as_group().children) { child->parent = &b; } } diff --git a/src/Hy3Node.hpp b/src/Hy3Node.hpp index 772d01f..7a52f3c 100644 --- a/src/Hy3Node.hpp +++ b/src/Hy3Node.hpp @@ -4,8 +4,9 @@ struct Hy3Node; struct Hy3GroupData; enum class Hy3GroupLayout; -#include +#include +#include #include #include "Hy3Layout.hpp" @@ -47,7 +48,6 @@ struct Hy3GroupData { void setLayout(Hy3GroupLayout layout); void setEphemeral(GroupEphemeralityOption ephemeral); -private: Hy3GroupData(Hy3GroupData&&); Hy3GroupData(const Hy3GroupData&) = delete; @@ -56,26 +56,28 @@ private: class Hy3NodeData { public: - Hy3NodeType type; - union { - Hy3GroupData as_group; - CWindow* as_window; - }; - - Hy3NodeData(); - Hy3NodeData(CWindow* window); + Hy3NodeData() = default; + Hy3NodeData(Hy3GroupData); + Hy3NodeData(PHLWINDOW window); Hy3NodeData(Hy3GroupLayout layout); - ~Hy3NodeData(); + Hy3NodeData(Hy3NodeData&&); + ~Hy3NodeData() = default; - Hy3NodeData& operator=(CWindow*); + Hy3NodeData& operator=(PHLWINDOW); Hy3NodeData& operator=(Hy3GroupLayout); + Hy3NodeData& operator=(Hy3NodeData&&); bool operator==(const Hy3NodeData&) const; - // private: - I give up, C++ wins - Hy3NodeData(Hy3GroupData); - Hy3NodeData(Hy3NodeData&&); - Hy3NodeData& operator=(Hy3NodeData&&); + bool valid() const; + Hy3NodeType type() const; + bool is_window() const; + bool is_group() const; + Hy3GroupData& as_group(); + PHLWINDOW as_window(); + +private: + std::variant data; }; struct Hy3Node { @@ -95,7 +97,7 @@ struct Hy3Node { void focus(); void focusWindow(); - CWindow* bringToTop(); + PHLWINDOW bringToTop(); void markFocused(); void raiseToTop(); Hy3Node* getFocusedNode(bool ignore_group_focus = false, bool stop_at_expanded = false); @@ -115,7 +117,7 @@ struct Hy3Node { void setHidden(bool); Hy3Node* findNodeForTabGroup(Hy3TabGroup&); - void appendAllWindows(std::vector&); + void appendAllWindows(std::vector&); std::string debugNode(); // Remove this node from its parent, deleting the parent if it was diff --git a/src/SelectionHook.cpp b/src/SelectionHook.cpp index 603ede6..ae5c051 100644 --- a/src/SelectionHook.cpp +++ b/src/SelectionHook.cpp @@ -6,15 +6,15 @@ namespace selection_hook { inline CFunctionHook* g_LastSelectionHook = nullptr; -void hook_updateDecos(void* thisptr, CWindow* window) { +void hook_updateDecos(void* thisptr, PHLWINDOW window) { bool explicitly_selected = g_Hy3Layout->shouldRenderSelected(window); - auto* lastWindow = g_pCompositor->m_pLastWindow; + auto lastWindow = g_pCompositor->m_pLastWindow; if (explicitly_selected) { g_pCompositor->m_pLastWindow = window; } - ((void (*)(void*, CWindow*)) g_LastSelectionHook->m_pOriginal)(thisptr, window); + ((void (*)(void*, PHLWINDOW)) g_LastSelectionHook->m_pOriginal)(thisptr, window); if (explicitly_selected) { g_pCompositor->m_pLastWindow = lastWindow; diff --git a/src/TabGroup.cpp b/src/TabGroup.cpp index d8005b4..86eb679 100644 --- a/src/TabGroup.cpp +++ b/src/TabGroup.cpp @@ -2,6 +2,8 @@ #include #include +#include +#include #include #include #include @@ -328,7 +330,7 @@ exitloop: // set stats from node data auto* parent = (*node)->parent; - auto& parent_group = parent->data.as_group; + auto& parent_group = parent->data.as_group(); entry->setFocused( parent_group.focused_child == *node @@ -433,11 +435,11 @@ void Hy3TabGroup::updateWithGroup(Hy3Node& node, bool warp) { if (warp) this->size.warp(); } - this->bar.updateNodeList(node.data.as_group.children); + this->bar.updateNodeList(node.data.as_group().children); this->bar.updateAnimations(warp); - if (node.data.as_group.focused_child != nullptr) { - this->updateStencilWindows(*node.data.as_group.focused_child); + if (node.data.as_group().focused_child != nullptr) { + this->updateStencilWindows(*node.data.as_group().focused_child); } } @@ -539,8 +541,9 @@ void Hy3TabGroup::renderTabBar() { glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - for (auto* window: this->stencil_windows) { - if (!g_pCompositor->windowExists(window)) continue; + for (auto windowref: this->stencil_windows) { + if (!valid(windowref)) continue; + auto window = windowref.lock(); auto wpos = window->m_vRealPosition.value() - monitor->vecPosition; auto wsize = window->m_vRealSize.value(); @@ -603,11 +606,11 @@ void Hy3TabGroup::renderTabBar() { } } -void findOverlappingWindows(Hy3Node& node, float height, std::vector& windows) { - switch (node.data.type) { - case Hy3NodeType::Window: windows.push_back(node.data.as_window); break; +void findOverlappingWindows(Hy3Node& node, float height, std::vector& windows) { + switch (node.data.type()) { + case Hy3NodeType::Window: windows.push_back(node.data.as_window()); break; case Hy3NodeType::Group: - auto& group = node.data.as_group; + auto& group = node.data.as_group(); switch (group.layout) { case Hy3GroupLayout::SplitH: diff --git a/src/TabGroup.hpp b/src/TabGroup.hpp index 3d77624..12117f3 100644 --- a/src/TabGroup.hpp +++ b/src/TabGroup.hpp @@ -85,7 +85,7 @@ private: class Hy3TabGroup { public: - CWindow* target_window = nullptr; + PHLWINDOW target_window = nullptr; PHLWORKSPACE workspace = nullptr; bool hidden = false; Hy3TabBar bar; @@ -102,7 +102,7 @@ public: void renderTabBar(); private: - std::vector stencil_windows; + std::vector stencil_windows; Vector2D last_pos; Vector2D last_size;