mirror of
https://github.com/Trensa-Organization/hy3.git
synced 2025-03-15 18:53:40 +01:00
fixup: fix breakage after hyprland#5762 + improve Hy3NodeData repr
Hy3NodeData now uses std::variant instead of a union, and all accesses are checked.
This commit is contained in:
parent
e6cabcfa3d
commit
dc5a0224ce
9 changed files with 431 additions and 403 deletions
19
flake.lock
generated
19
flake.lock
generated
|
@ -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": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
inputs = {
|
||||
hyprland.url = "github:hyprwm/Hyprland?ref=da839f20f1b1a57ec78d6b041f8d1369150d253e";
|
||||
hyprland.url = "github:hyprwm/Hyprland";
|
||||
};
|
||||
|
||||
outputs = { self, hyprland, ... }: let
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <hyprland/src/Compositor.hpp>
|
||||
#include <hyprland/src/desktop/DesktopTypes.hpp>
|
||||
#include <hyprland/src/desktop/Workspace.hpp>
|
||||
#include <hyprland/src/plugins/PluginAPI.hpp>
|
||||
#include <ranges>
|
||||
|
||||
|
@ -15,18 +16,18 @@ std::shared_ptr<HOOK_CALLBACK_FN> windowTitleHookPtr;
|
|||
std::shared_ptr<HOOK_CALLBACK_FN> urgentHookPtr;
|
||||
std::shared_ptr<HOOK_CALLBACK_FN> 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<Hyprlang::INT>("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<CWindow*> windows;
|
||||
std::vector<PHLWINDOW> 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<CWindow*>(data);
|
||||
auto window = std::any_cast<PHLWINDOW>(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<CWindow*>(data);
|
||||
auto window = std::any_cast<PHLWINDOW>(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<Hyprlang::INT>("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<Hy3Node*>::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))
|
||||
{
|
||||
|
|
|
@ -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<Hy3TabGroup> 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
|
||||
|
|
360
src/Hy3Node.cpp
360
src/Hy3Node.cpp
|
@ -1,6 +1,10 @@
|
|||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <variant>
|
||||
|
||||
#include <bits/ranges_util.h>
|
||||
#include <hyprland/src/Compositor.hpp>
|
||||
#include <hyprland/src/defines.hpp>
|
||||
#include <hyprland/src/helpers/Box.hpp>
|
||||
#include <hyprland/src/plugins/PluginAPI.hpp>
|
||||
|
||||
|
@ -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<PHLWINDOWREF>(node.data)) {
|
||||
this->data.emplace<0>(std::get<PHLWINDOWREF>(node.data));
|
||||
} else if (std::holds_alternative<Hy3GroupData>(node.data)) {
|
||||
this->data.emplace<1>(std::move(std::get<Hy3GroupData>(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<Hy3GroupData>(this->data)) {
|
||||
return true;
|
||||
} else if (std::holds_alternative<PHLWINDOWREF>(this->data)) {
|
||||
return !std::get<PHLWINDOWREF>(this->data).expired();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Hy3NodeType Hy3NodeData::type() const {
|
||||
if (std::holds_alternative<Hy3GroupData>(this->data)) {
|
||||
return Hy3NodeType::Group;
|
||||
} else if (std::holds_alternative<PHLWINDOWREF>(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<Hy3GroupData>(this->data)) {
|
||||
return std::get<Hy3GroupData>(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<PHLWINDOWREF>(this->data)) {
|
||||
auto& ref = std::get<PHLWINDOWREF>(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<CWindow*>& list) {
|
||||
switch (this->data.type) {
|
||||
case Hy3NodeType::Window: list.push_back(this->data.as_window); break;
|
||||
void Hy3Node::appendAllWindows(std::vector<PHLWINDOW>& 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<CWindow*>& 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,10 +800,11 @@ 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
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,9 @@ struct Hy3Node;
|
|||
struct Hy3GroupData;
|
||||
enum class Hy3GroupLayout;
|
||||
|
||||
#include <list>
|
||||
#include <variant>
|
||||
|
||||
#include <hyprland/src/defines.hpp>
|
||||
#include <hyprland/src/desktop/Window.hpp>
|
||||
|
||||
#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<PHLWINDOWREF, Hy3GroupData> 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<CWindow*>&);
|
||||
void appendAllWindows(std::vector<PHLWINDOW>&);
|
||||
std::string debugNode();
|
||||
|
||||
// Remove this node from its parent, deleting the parent if it was
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <cairo/cairo.h>
|
||||
#include <hyprland/src/Compositor.hpp>
|
||||
#include <hyprland/src/desktop/DesktopTypes.hpp>
|
||||
#include <hyprland/src/desktop/Workspace.hpp>
|
||||
#include <hyprland/src/helpers/Box.hpp>
|
||||
#include <hyprland/src/helpers/Color.hpp>
|
||||
#include <hyprland/src/render/OpenGL.hpp>
|
||||
|
@ -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<CWindow*>& windows) {
|
||||
switch (node.data.type) {
|
||||
case Hy3NodeType::Window: windows.push_back(node.data.as_window); break;
|
||||
void findOverlappingWindows(Hy3Node& node, float height, std::vector<PHLWINDOWREF>& 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:
|
||||
|
|
|
@ -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<CWindow*> stencil_windows;
|
||||
std::vector<PHLWINDOWREF> stencil_windows;
|
||||
Vector2D last_pos;
|
||||
Vector2D last_size;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue