diff --git a/CHANGELOG.md b/CHANGELOG.md index b71ed0e..ec064b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,10 +9,7 @@ - Implement `resizeactivewindow` for floating windows - Fully implement `resizeactivewindow` for tiled windows -- `hy3:resizenode` added, drop-in replacement for `resizeactivewindow` applied to a whole node. -- Implement keyboard-based focusing for floating windows -- Implement keyboard-based movement for floating windows - - Add configuration `kbd_shift_delta` providing delta [in pixels] for shift + ## hl0.35.0 and before - Fixed `hy3:killactive` and `hy3:movetoworkspace` not working in fullscreen. diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100755 new mode 100644 index e639687..e4e83ac --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,6 @@ pkg_check_modules(DEPS REQUIRED hyprland pixman-1 libdrm pango pangocairo) add_library(hy3 SHARED src/main.cpp src/dispatchers.cpp - src/conversions.cpp src/Hy3Layout.cpp src/Hy3Node.cpp src/TabGroup.cpp diff --git a/LICENSE b/LICENSE old mode 100755 new mode 100644 diff --git a/README.md b/README.md old mode 100755 new mode 100644 index f025f66..3c78f0f --- a/README.md +++ b/README.md @@ -318,3 +318,4 @@ plugin { - `shrink` - shrink by one node - `base` - undo all expansions + diff --git a/compile_commands_bear.sh b/compile_commands_bear.sh new file mode 100755 index 0000000..2466693 --- /dev/null +++ b/compile_commands_bear.sh @@ -0,0 +1,4 @@ +rm -rf build +cmake -DCMAKE_BUILD_TYPE=Debug -DHY3_NO_VERSION_CHECK=TRUE -B build +bear -- cmake --build build -j16 +sed -i 's/-std=gnu++23/-std=gnu++2b/g' compile_commands.json diff --git a/flake.lock b/flake.lock old mode 100755 new mode 100644 diff --git a/flake.nix b/flake.nix old mode 100755 new mode 100644 diff --git a/hyprpm.toml b/hyprpm.toml index 0749bca..d5b8bc7 100644 --- a/hyprpm.toml +++ b/hyprpm.toml @@ -1,6 +1,6 @@ [repository] name = "hy3" -authors = ["outfoxxed, DRAGONTOS"] +authors = ["outfoxxed", "DRAGONTOS"] commit_pins = [ ["03ebbe18ed8517ee22591eac82cd54322f42cb7d", "2f28dc810c0e1f42763a1f14fb011c4fce6db8be"], ["84ab8d11e8951a6551d1e1bf87796a8589da6d47", "d3e20856a9896f28b506195b31407eddc6df2e20"], @@ -10,7 +10,7 @@ commit_pins = [ [hy3] description = "i3 like tiling for hyprland" -authors = ["outfoxxed, DRAGONTOS"] +authors = ["outfoxxed", "DRAGONTOS"] output = "build/libhy3.so" build = [ "cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -B build", diff --git a/src/BitFlag.hpp b/src/BitFlag.hpp deleted file mode 100644 index 6253157..0000000 --- a/src/BitFlag.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -template -struct BitFlag { - int m_FlagValue = 0; - - BitFlag() = default; - - BitFlag(FlagType flag) { m_FlagValue = (int) flag; } - - operator FlagType() const { return static_cast(m_FlagValue); } - - void Set(FlagType flag) { m_FlagValue |= (int) flag; } - - void Unset(FlagType flag) { m_FlagValue &= ~(int) flag; } - - void Toggle(FlagType flag) { m_FlagValue ^= (int) flag; } - - void Mask(FlagType flag) { m_FlagValue &= (int) flag; } - - bool Has(FlagType flag) const { return (m_FlagValue & (int) flag) == (int) flag; } - - bool HasAny(FlagType flag) const { return (m_FlagValue & (int) flag) != 0; } - bool HasNot(FlagType flag) const { return (m_FlagValue & (int) flag) != (int) flag; } - - const BitFlag& operator|=(FlagType flag) { - Set(flag); - return *this; - } - - const BitFlag& operator&=(FlagType flag) { - Mask(flag); - return *this; - } - - const BitFlag& operator^=(FlagType flag) { - Toggle(flag); - return *this; - } - - bool operator==(FlagType flag) const { return m_FlagValue == (int) flag; } - - bool operator!=(FlagType flag) const { return m_FlagValue != (int) flag; } -}; diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp index e3bcda0..e73087a 100644 --- a/src/Hy3Layout.cpp +++ b/src/Hy3Layout.cpp @@ -1,17 +1,12 @@ -#include -#include #include #include #include #include -#include #include -#include "BitFlag.hpp" #include "Hy3Layout.hpp" #include "SelectionHook.hpp" -#include "conversions.hpp" #include "globals.hpp" std::unique_ptr renderHookPtr = @@ -174,7 +169,7 @@ void Hy3Layout::insertNode(Hy3Node& node) { if (opening_after != nullptr && ((node.data.type == Hy3NodeType::Group - && (opening_after == &node || node.hasChild(opening_after))) + && (opening_after == &node || node.data.as_group.hasChild(opening_after))) || opening_after->reparenting)) { opening_after = nullptr; @@ -292,7 +287,6 @@ void Hy3Layout::insertNode(Hy3Node& node) { } void Hy3Layout::onWindowRemovedTiling(CWindow* window) { - this->m_focusIntercepts.erase(window); static const auto node_collapse_policy = ConfigValue("plugin:hy3:node_collapse_policy"); @@ -348,14 +342,12 @@ void Hy3Layout::onWindowRemovedTiling(CWindow* window) { } } -void Hy3Layout::onWindowRemovedFloating(CWindow* window) { this->m_focusIntercepts.erase(window); } - void Hy3Layout::onWindowFocusChange(CWindow* window) { auto* node = this->getNodeFromWindow(window); if (node == nullptr) return; hy3_log( - LOG, + TRACE, "changing window focus to window {:x} as node {:x}", (uintptr_t) window, (uintptr_t) node @@ -380,10 +372,16 @@ void Hy3Layout::recalculateMonitor(const int& monitor_id) { // todo: refactor this auto* top_node = this->getWorkspaceRootGroup(monitor->activeWorkspace); - if (top_node == nullptr) { - top_node = this->getWorkspaceRootGroup(monitor->specialWorkspaceID); + if (top_node != nullptr) { + top_node->position = monitor->vecPosition + monitor->vecReservedTopLeft; + top_node->size = + monitor->vecSize - monitor->vecReservedTopLeft - monitor->vecReservedBottomRight; + + top_node->recalcSizePosRecursive(); } + top_node = this->getWorkspaceRootGroup(monitor->specialWorkspaceID); + if (top_node != nullptr) { top_node->position = monitor->vecPosition + monitor->vecReservedTopLeft; top_node->size = @@ -409,114 +407,90 @@ ShiftDirection reverse(ShiftDirection direction) { } } -void executeResizeOperation( - const Vector2D& delta, - eRectCorner corner, - Hy3Node* node, - CMonitor* monitor -) { - if (node == nullptr) return; - if (monitor == nullptr) return; - - const bool display_left = - STICKS(node->position.x, monitor->vecPosition.x + monitor->vecReservedTopLeft.x); - const bool display_right = STICKS( - node->position.x + node->size.x, - monitor->vecPosition.x + monitor->vecSize.x - monitor->vecReservedBottomRight.x - ); - const bool display_top = - STICKS(node->position.y, monitor->vecPosition.y + monitor->vecReservedTopLeft.y); - const bool display_bottom = STICKS( - node->position.y + node->size.y, - monitor->vecPosition.y + monitor->vecSize.y - monitor->vecReservedBottomRight.y - ); - - 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)); - - if (node_is_root) { - if (display_left && display_right) resize_delta.x = 0; - if (display_top && display_bottom) resize_delta.y = 0; - } - - // Don't execute the logic unless there's something to do - if (resize_delta.x != 0 || resize_delta.y != 0) { - ShiftDirection target_edge_x; - ShiftDirection target_edge_y; - - // Determine the direction in which we're going to look for the neighbor node - // that will be resized - if (corner == CORNER_NONE) { // It's probably a keyboard event. - target_edge_x = display_right ? ShiftDirection::Left : ShiftDirection::Right; - target_edge_y = display_bottom ? ShiftDirection::Up : ShiftDirection::Down; - - // If the anchor is not at the top/left then reverse the delta - if (target_edge_x == ShiftDirection::Left) resize_delta.x = -resize_delta.x; - if (target_edge_y == ShiftDirection::Up) resize_delta.y = -resize_delta.y; - } else { // It's probably a mouse event - // Resize against the edges corresponding to the selected corner - target_edge_x = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT - ? ShiftDirection::Left - : ShiftDirection::Right; - target_edge_y = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT ? ShiftDirection::Up - : ShiftDirection::Down; - } - - // Find the neighboring node in each axis, which will be either above or at the - // same level as the initiating node in the layout hierarchy. These are the nodes - // which must get resized (rather than the initiator) because they are the - // highest point in the hierarchy - auto horizontal_neighbor = node->findNeighbor(target_edge_x); - auto vertical_neighbor = node->findNeighbor(target_edge_y); - - static const auto animate = ConfigValue("misc:animate_manual_resizes"); - - // Note that the resize direction is reversed, because from the neighbor's perspective - // the edge to be moved is the opposite way round. However, the delta is still the same. - if (horizontal_neighbor) { - horizontal_neighbor->resize(reverse(target_edge_x), resize_delta.x, *animate == 0); - } - - if (vertical_neighbor) { - vertical_neighbor->resize(reverse(target_edge_y), resize_delta.y, *animate == 0); - } - } -} - -void Hy3Layout::resizeNode(const Vector2D& delta, eRectCorner corner, Hy3Node* node) { - // Is the intended target really a node or a floating window? - auto window = g_pCompositor->m_pLastWindow; - if (window && window->m_bIsFloating) { - this->resizeActiveWindow(delta, corner, window); - } else if (node) { - auto monitor = g_pCompositor->getMonitorFromID( - g_pCompositor->getWorkspaceByID(node->workspace_id)->m_iMonitorID - ); - executeResizeOperation(delta, corner, node, monitor); - } -} - void Hy3Layout::resizeActiveWindow(const Vector2D& delta, eRectCorner corner, CWindow* pWindow) { auto window = pWindow ? pWindow : g_pCompositor->m_pLastWindow; - if (window == nullptr || !g_pCompositor->windowValidMapped(window)) return; + if (!g_pCompositor->windowValidMapped(window)) return; - if (window->m_bIsFloating) { - // Use the same logic as the `main` layout for floating windows + auto* node = this->getNodeFromWindow(window); + + if (node != nullptr) { + node = &node->getExpandActor(); + + auto monitor = g_pCompositor->getMonitorFromID(window->m_iMonitorID); + + const bool display_left = + STICKS(node->position.x, monitor->vecPosition.x + monitor->vecReservedTopLeft.x); + const bool display_right = STICKS( + node->position.x + node->size.x, + monitor->vecPosition.x + monitor->vecSize.x - monitor->vecReservedBottomRight.x + ); + const bool display_top = + STICKS(node->position.y, monitor->vecPosition.y + monitor->vecReservedTopLeft.y); + const bool display_bottom = STICKS( + node->position.y + node->size.y, + monitor->vecPosition.y + monitor->vecSize.y - monitor->vecReservedBottomRight.y + ); + + 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)); + + if (node_is_root) { + if (display_left && display_right) resize_delta.x = 0; + if (display_top && display_bottom) resize_delta.y = 0; + } + + // Don't execute the logic unless there's something to do + if (resize_delta.x != 0 || resize_delta.y != 0) { + ShiftDirection target_edge_x; + ShiftDirection target_edge_y; + + // Determine the direction in which we're going to look for the neighbor node + // that will be resized + if (corner == CORNER_NONE) { // It's probably a keyboard event. + target_edge_x = display_right ? ShiftDirection::Left : ShiftDirection::Right; + target_edge_y = display_bottom ? ShiftDirection::Up : ShiftDirection::Down; + + // If the anchor is not at the top/left then reverse the delta + if (target_edge_x == ShiftDirection::Left) resize_delta.x = -resize_delta.x; + if (target_edge_y == ShiftDirection::Up) resize_delta.y = -resize_delta.y; + } else { // It's probably a mouse event + // Resize against the edges corresponding to the selected corner + target_edge_x = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT + ? ShiftDirection::Left + : ShiftDirection::Right; + target_edge_y = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT + ? ShiftDirection::Up + : ShiftDirection::Down; + } + + // Find the neighboring node in each axis, which will be either above or at the + // same level as the initiating node in the layout hierarchy. These are the nodes + // which must get resized (rather than the initiator) because they are the + // highest point in the hierarchy + auto horizontal_neighbor = node->findNeighbor(target_edge_x); + auto vertical_neighbor = node->findNeighbor(target_edge_y); + + static const auto animate = ConfigValue("misc:animate_manual_resizes"); + + // Note that the resize direction is reversed, because from the neighbor's perspective + // the edge to be moved is the opposite way round. However, the delta is still the same. + if (horizontal_neighbor) { + horizontal_neighbor->resize(reverse(target_edge_x), resize_delta.x, *animate == 0); + } + + if (vertical_neighbor) { + vertical_neighbor->resize(reverse(target_edge_y), resize_delta.y, *animate == 0); + } + } + } else if (window->m_bIsFloating) { + // No parent node - is this a floating window? If so, use the same logic as the `main` layout const auto required_size = Vector2D( - std::max((window->m_vRealSize.goalv() + delta).x, 20.0), - std::max((window->m_vRealSize.goalv() + delta).y, 20.0) + std::max((window->m_vRealSize.goal() + delta).x, 20.0), + std::max((window->m_vRealSize.goal() + delta).y, 20.0) ); window->m_vRealSize = required_size; - g_pXWaylandManager->setWindowSize(window, required_size); - } else if (auto* node = this->getNodeFromWindow(window); node != nullptr) { - executeResizeOperation( - delta, - corner, - &node->getExpandActor(), - g_pCompositor->getMonitorFromID(window->m_iMonitorID) - ); } } @@ -556,10 +530,10 @@ void Hy3Layout::fullscreenRequestForWindow( // save position and size if floating if (window->m_bIsFloating) { - window->m_vLastFloatingPosition = window->m_vRealPosition.goalv(); - window->m_vPosition = window->m_vRealPosition.goalv(); - window->m_vLastFloatingSize = window->m_vRealSize.goalv(); - window->m_vSize = window->m_vRealSize.goalv(); + window->m_vLastFloatingPosition = window->m_vRealPosition.goal(); + window->m_vPosition = window->m_vRealPosition.goal(); + window->m_vLastFloatingSize = window->m_vRealSize.goal(); + window->m_vSize = window->m_vRealSize.goal(); } if (fullscreen_mode == FULLSCREEN_FULL) { @@ -599,7 +573,7 @@ void Hy3Layout::fullscreenRequestForWindow( } g_pCompositor->updateWindowAnimatedDecorationValues(window); - g_pXWaylandManager->setWindowSize(window, window->m_vRealSize.goalv()); + g_pXWaylandManager->setWindowSize(window, window->m_vRealSize.goal()); g_pCompositor->changeWindowZOrder(window, true); this->recalculateMonitor(monitor->ID); } @@ -635,26 +609,16 @@ void Hy3Layout::switchWindows(CWindow* pWindowA, CWindow* pWindowB) { void Hy3Layout::moveWindowTo(CWindow* window, const std::string& direction) { auto* node = this->getNodeFromWindow(window); - if (node == nullptr) { - const auto neighbor = g_pCompositor->getWindowInDirection(window, direction[0]); + if (node == nullptr) return; - if (window->m_iWorkspaceID != neighbor->m_iWorkspaceID) { - // if different monitors, send to monitor - onWindowRemovedTiling(window); - window->moveToWorkspace(neighbor->m_iWorkspaceID); - window->m_iMonitorID = neighbor->m_iMonitorID; - onWindowCreatedTiling(window); - } - } else { - ShiftDirection shift; - if (direction == "l") shift = ShiftDirection::Left; - else if (direction == "r") shift = ShiftDirection::Right; - else if (direction == "u") shift = ShiftDirection::Up; - else if (direction == "d") shift = ShiftDirection::Down; - else return; + ShiftDirection shift; + if (direction == "l") shift = ShiftDirection::Left; + else if (direction == "r") shift = ShiftDirection::Right; + else if (direction == "u") shift = ShiftDirection::Up; + else if (direction == "d") shift = ShiftDirection::Down; + else return; - this->shiftNode(*node, shift, false, false); - } + this->shiftNode(*node, shift, false, false); } void Hy3Layout::alterSplitRatio(CWindow* pWindow, float delta, bool exact) { @@ -904,423 +868,43 @@ void Hy3Layout::shiftNode(Hy3Node& node, ShiftDirection direction, bool once, bo } } -void shiftFloatingWindow(CWindow* window, ShiftDirection direction) { - static const auto kbd_shift_delta = ConfigValue("plugin:hy3:kbd_shift_delta"); +void Hy3Layout::shiftWindow(int workspace, ShiftDirection direction, bool once, bool visible) { + auto* node = this->getWorkspaceFocusedNode(workspace); + if (node == nullptr) return; - if (!window) return; + this->shiftNode(*node, direction, once, visible); +} - Vector2D bounds {0, 0}; - // BUG: Assumes horizontal monitor layout - // BUG: Ignores monitor reserved space - for (auto m: g_pCompositor->m_vMonitors) { - bounds.x = std::max(bounds.x, m->vecPosition.x + m->vecSize.x); - if (m->ID == window->m_iMonitorID) { - bounds.y = m->vecPosition.y + m->vecSize.y; +void Hy3Layout::shiftFocus(int workspace, ShiftDirection direction, bool visible) { + auto* current_window = g_pCompositor->m_pLastWindow; + + if (current_window != nullptr) { + auto* p_workspace = g_pCompositor->getWorkspaceByID(current_window->m_iWorkspaceID); + if (p_workspace->m_bHasFullscreenWindow) return; + + if (current_window->m_bIsFloating) { + auto* next_window = g_pCompositor->getWindowInDirection( + current_window, + direction == ShiftDirection::Left ? 'l' + : direction == ShiftDirection::Up ? 'u' + : direction == ShiftDirection::Down ? 'd' + : 'r' + ); + + if (next_window != nullptr) g_pCompositor->focusWindow(next_window); + return; } } - const int delta = getSearchDirection(direction) == SearchDirection::Forwards ? *kbd_shift_delta - : -*kbd_shift_delta; + auto* node = this->getWorkspaceFocusedNode(workspace); + if (node == nullptr) return; - Vector2D movement_delta = - (getAxis(direction) == Axis::Horizontal) ? Vector2D {delta, 0} : Vector2D {0, delta}; + auto* target = this->shiftOrGetFocus(*node, direction, false, false, visible); - auto window_pos = window->m_vRealPosition.vec(); - auto window_size = window->m_vRealSize.vec(); - - // Keep at least `delta` pixels visible - if (window_pos.x + window_size.x + delta < 0 || window_pos.x + delta > bounds.x) - movement_delta.x = 0; - if (window_pos.y + window_size.y + delta < 0 || window_pos.y + delta > bounds.y) - movement_delta.y = 0; - if (movement_delta.x != 0 || movement_delta.y != 0) { - auto new_pos = window_pos + movement_delta; - // Do we need to change the workspace? - const auto new_monitor = g_pCompositor->getMonitorFromVector(new_pos); - if (new_monitor && new_monitor->ID != window->m_iMonitorID) { - // Ignore the movement request if the new workspace is special - if (!new_monitor->specialWorkspaceID) { - const auto old_workspace = g_pCompositor->getWorkspaceByID(window->m_iWorkspaceID); - const auto new_workspace = g_pCompositor->getWorkspaceByID(new_monitor->activeWorkspace); - const auto previous_monitor = g_pCompositor->getMonitorFromID(window->m_iMonitorID); - const auto original_new_pos = new_pos; - - if (new_workspace && previous_monitor) { - switch (direction) { - case ShiftDirection::Left: new_pos.x += new_monitor->vecSize.x; break; - case ShiftDirection::Right: new_pos.x -= previous_monitor->vecSize.x; break; - case ShiftDirection::Up: new_pos.y += new_monitor->vecSize.y; break; - case ShiftDirection::Down: new_pos.y -= previous_monitor->vecSize.y; break; - default: UNREACHABLE(); - } - } - - window->m_vRealPosition = new_pos; - g_pCompositor->moveWindowToWorkspaceSafe(window, new_workspace); - g_pCompositor->setActiveMonitor(new_monitor); - - const static auto allow_workspace_cycles = - ConfigValue("binds:allow_workspace_cycles"); - if (*allow_workspace_cycles) new_workspace->rememberPrevWorkspace(old_workspace); - } - } else { - window->m_vRealPosition = new_pos; - } - } -} - -void Hy3Layout::shiftWindow(int workspace_id, ShiftDirection direction, bool once, bool visible) { - auto focused_window = g_pCompositor->m_pLastWindow; - auto* node = getWorkspaceFocusedNode(workspace_id); - - if (focused_window && focused_window->m_bIsFloating) { - shiftFloatingWindow(focused_window, direction); - } else if (node) { - shiftNode(*node, direction, once, visible); - } -} - -void Hy3Layout::focusMonitor(CMonitor* monitor) { - if (monitor == nullptr) return; - - g_pCompositor->setActiveMonitor(monitor); - const auto focusedNode = this->getWorkspaceFocusedNode(monitor->activeWorkspace); - if (focusedNode != nullptr) { - focusedNode->focus(); - } else { - auto* workspace = g_pCompositor->getWorkspaceByID(monitor->activeWorkspace); - CWindow* next_window = nullptr; - if (workspace != nullptr) { - workspace->setActive(true); - if (workspace->m_bHasFullscreenWindow) { - next_window = g_pCompositor->getFullscreenWindowOnWorkspace(workspace->m_iID); - } else { - next_window = workspace->getLastFocusedWindow(); - } - } else { - for (auto& w: g_pCompositor->m_vWindows | std::views::reverse) { - if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 - && w->m_iWorkspaceID == next_window->m_iWorkspaceID && !w->m_bX11ShouldntFocus - && !w->m_sAdditionalConfigData.noFocus) - { - next_window = w.get(); - break; - } - } - } - g_pCompositor->focusWindow(next_window); - } -} - -CWindow* getFocusedWindow(const Hy3Node* node) { - auto search = node; - while (search != nullptr && search->data.type == Hy3NodeType::Group) { - search = search->data.as_group.focused_child; - } - - if (search == nullptr || search->data.type != Hy3NodeType::Window) { - return nullptr; - } - - return search->data.as_window; -} - -bool shiftIsForward(ShiftDirection direction) { - return direction == ShiftDirection::Right || direction == ShiftDirection::Down; -} - -bool shiftIsVertical(ShiftDirection direction) { - return direction == ShiftDirection::Up || direction == ShiftDirection::Down; -} - -bool shiftMatchesLayout(Hy3GroupLayout layout, ShiftDirection direction) { - return (layout == Hy3GroupLayout::SplitV && shiftIsVertical(direction)) - || (layout != Hy3GroupLayout::SplitV && !shiftIsVertical(direction)); -} - -bool covers(const CBox& outer, const CBox& inner) { - return outer.x <= inner.x && outer.y <= inner.y && outer.x + outer.w >= inner.x + inner.w - && outer.y + outer.h >= inner.y + inner.h; -} - -bool isObscured(CWindow* window) { - if (!window) return false; - - const auto inner_box = window->getWindowMainSurfaceBox(); - - bool is_obscured = false; - for (auto& w: g_pCompositor->m_vWindows | std::views::reverse) { - if (w.get() == window) { - // Don't go any further if this is a floating window, because m_vWindows is sorted bottom->top - // per Compositor.cpp - if (window->m_bIsFloating) break; - else continue; - } - - if (!w->m_bIsFloating) continue; - - const auto outer_box = w->getWindowMainSurfaceBox(); - is_obscured = covers(outer_box, inner_box); - - if (is_obscured) break; - }; - - return is_obscured; -} - -bool isObscured(Hy3Node* node) { - return node && node->data.type == Hy3NodeType::Window && isObscured(node->data.as_window); -} - -bool isNotObscured(CWindow* window) { return !isObscured(window); } -bool isNotObscured(Hy3Node* node) { return !isObscured(node); } - -CWindow* getWindowInDirection( - CWindow* source, - ShiftDirection direction, - BitFlag layers_same_monitor, - BitFlag layers_other_monitors -) { - if (!source) return nullptr; - if (layers_other_monitors == Layer::None && layers_same_monitor == Layer::None) return nullptr; - - CWindow* target_window = nullptr; - const auto source_middle = source->middle(); - std::optional target_distance; - - const auto static focus_policy = - ConfigValue("plugin:hy3:focus_obscured_windows_policy"); - bool permit_obscured_windows = - *focus_policy == 0 - || (*focus_policy == 2 && layers_same_monitor.HasNot(Layer::Floating | Layer::Tiled)); - - const auto source_monitor = g_pCompositor->getMonitorFromID(source->m_iMonitorID); - const auto next_monitor = - layers_other_monitors.HasAny(Layer::Floating | Layer::Tiled) - ? g_pCompositor->getMonitorInDirection(source_monitor, directionToChar(direction)) - : nullptr; - - const auto next_workspace = next_monitor ? next_monitor->specialWorkspaceID - ? next_monitor->specialWorkspaceID - : next_monitor->activeWorkspace - : WORKSPACE_INVALID; - - auto isCandidate = [=, mon = source->m_iMonitorID](CWindow* w) { - const auto window_layer = w->m_bIsFloating ? Layer::Floating : Layer::Tiled; - const auto monitor_flags = w->m_iMonitorID == mon ? layers_same_monitor : layers_other_monitors; - - return (monitor_flags.Has(window_layer)) && w->m_bIsMapped && w->m_iX11Type != 2 - && !w->m_sAdditionalConfigData.noFocus && !w->isHidden() && !w->m_bX11ShouldntFocus - && (w->m_bPinned || w->m_iWorkspaceID == source->m_iWorkspaceID - || w->m_iWorkspaceID == next_workspace); - }; - - for (auto& pw: g_pCompositor->m_vWindows) { - auto w = pw.get(); - if (w != source && isCandidate(w)) { - auto dist = Distance {direction, source_middle, w->middle()}; - if ((target_distance.has_value() ? dist < target_distance.value() - : dist.isInDirection(direction)) - && (permit_obscured_windows || isNotObscured(w))) - { - target_window = w; - target_distance = dist; - } - } - } - - hy3_log(LOG, "getWindowInDirection: closest window to {} is {}", source, target_window); - - // If the closest window is on a different monitor and the nearest edge has the same position - // as the last focused window on that monitor's workspace then choose the last focused window - // instead; this allows seamless back-and-forth by direction keys - if (target_window && target_window->m_iMonitorID != source->m_iMonitorID) { - if (auto new_workspace = g_pCompositor->getWorkspaceByID(next_workspace)) { - if (auto last_focused = new_workspace->getLastFocusedWindow()) { - auto target_bounds = - CBox(target_window->m_vRealPosition.vec(), target_window->m_vRealSize.vec()); - auto last_focused_bounds = - CBox(last_focused->m_vRealPosition.vec(), last_focused->m_vRealSize.vec()); - - if ((direction == ShiftDirection::Left - && STICKS( - target_bounds.x + target_bounds.w, - last_focused_bounds.x + last_focused_bounds.w - )) - || (direction == ShiftDirection::Right && STICKS(target_bounds.x, last_focused_bounds.x) - ) - || (direction == ShiftDirection::Up - && STICKS( - target_bounds.y + target_bounds.h, - last_focused_bounds.y + last_focused_bounds.h - )) - || (direction == ShiftDirection::Down && STICKS(target_bounds.y, last_focused_bounds.y) - )) - { - target_window = last_focused; - } - } - } - } - - return target_window; -} - -void Hy3Layout::shiftFocusToMonitor(ShiftDirection direction) { - auto target_monitor = g_pCompositor->getMonitorInDirection(directionToChar(direction)); - if (target_monitor) this->focusMonitor(target_monitor); -} - -void Hy3Layout::shiftFocus( - int workspace, - ShiftDirection direction, - bool visible, - BitFlag eligible_layers -) { - Hy3Node* candidate_node = nullptr; - CWindow* closest_window = nullptr; - Hy3Node* source_node = nullptr; - CWindow* source_window = g_pCompositor->m_pLastWindow; - CWorkspace* source_workspace = g_pCompositor->getWorkspaceByID(workspace); - - if (source_workspace) { - source_window = source_workspace->m_pLastFocusedWindow; - } else { - source_window = g_pCompositor->m_pLastWindow; - } - - if (source_window == nullptr || (source_workspace && source_workspace->m_bHasFullscreenWindow)) { - shiftFocusToMonitor(direction); - return; - } - - hy3_log( - LOG, - "shiftFocus: Source: {} ({}), workspace: {}, direction: {}, visible: {}", - source_window, - source_window->m_bIsFloating ? "floating" : "tiled", - workspace, - (int) direction, - visible - ); - - // If no eligible_layers specified then choose the same layer as the source window - if (eligible_layers == Layer::None) - eligible_layers = source_window->m_bIsFloating ? Layer::Floating : Layer::Tiled; - - const auto static focus_policy = - ConfigValue("plugin:hy3:focus_obscured_windows_policy"); - bool skip_obscured = *focus_policy == 1 - || (*focus_policy == 2 && eligible_layers.Has(Layer::Floating | Layer::Tiled)); - - // Determine the starting point for looking for a tiled node - it's either the - // workspace's focused node or the floating window's focus entry point (which may be null) - if (eligible_layers.Has(Layer::Tiled)) { - source_node = source_window->m_bIsFloating ? getFocusOverride(source_window, direction) - : getWorkspaceFocusedNode(workspace); - - if (source_node) { - candidate_node = this->shiftOrGetFocus(*source_node, direction, false, false, visible); - while (candidate_node && skip_obscured && isObscured(candidate_node)) { - candidate_node = this->shiftOrGetFocus(*candidate_node, direction, false, false, visible); - } - } - } - - BitFlag this_monitor = eligible_layers & Layer::Floating; - if (source_window->m_bIsFloating && !candidate_node) - this_monitor |= (eligible_layers & Layer::Tiled); - - BitFlag other_monitors; - if (!candidate_node) other_monitors |= eligible_layers; - - // Find the closest window in the right direction. Consider other monitors - // if we don't have a tiled candidate - closest_window = getWindowInDirection(source_window, direction, this_monitor, other_monitors); - - // If there's a window in the right direction then choose between that window and the tiled - // candidate. - bool focus_closest_window = false; - if (closest_window) { - if (candidate_node) { - // If the closest window is tiled then focus the tiled node which was obtained from - // `shiftOrGetFocus`, otherwise focus whichever is closer - if (closest_window->m_bIsFloating) { - Distance distanceToClosestWindow( - direction, - source_window->middle(), - closest_window->middle() - ); - Distance distanceToTiledNode(direction, source_window->middle(), candidate_node->middle()); - - if (distanceToClosestWindow < distanceToTiledNode) { - focus_closest_window = true; - } - } - } else { - focus_closest_window = true; - } - } - - std::optional new_monitor_id; - if (focus_closest_window) { - new_monitor_id = closest_window->m_iMonitorID; - setFocusOverride(closest_window, direction, source_node); - g_pCompositor->focusWindow(closest_window); - } else if (candidate_node) { - if (candidate_node->data.type == Hy3NodeType::Window) { - new_monitor_id = candidate_node->data.as_window->m_iMonitorID; - } else if (auto* workspace = g_pCompositor->getWorkspaceByID(candidate_node->getRoot()->workspace_id)) - { - new_monitor_id = workspace->m_iMonitorID; - } - candidate_node->focusWindow(); - candidate_node->getRoot()->recalcSizePosRecursive(); - } else { - shiftFocusToMonitor(direction); - } - - if (new_monitor_id && new_monitor_id.value() != source_window->m_iMonitorID) { - if (auto* monitor = g_pCompositor->getMonitorFromID(new_monitor_id.value())) { - g_pCompositor->setActiveMonitor(monitor); - } - } -} - -Hy3Node* Hy3Layout::getFocusOverride(CWindow* src, ShiftDirection direction) { - if (auto intercept = this->m_focusIntercepts.find(src); - intercept != this->m_focusIntercepts.end()) - { - Hy3Node** accessor = intercept->second.forDirection(direction); - - if (auto override = *accessor) { - // If the root isn't valid or is on a different workspsace then update the intercept data - if (override->workspace_id != src->m_iWorkspaceID - || !std::ranges::contains(this->nodes, *override)) - { - *accessor = nullptr; - // If there are no remaining overrides then discard the intercept - if (intercept->second.isEmpty()) { - this->m_focusIntercepts.erase(intercept); - } - } - - return override; - } - } - - return nullptr; -} - -void Hy3Layout::setFocusOverride(CWindow* src, ShiftDirection direction, Hy3Node* dest) { - if (auto intercept = this->m_focusIntercepts.find(src); - intercept != this->m_focusIntercepts.end()) - { - *intercept->second.forDirection(direction) = dest; - } else { - FocusOverride override; - *override.forDirection(direction) = dest; - this->m_focusIntercepts.insert({src, override}); + if (target != nullptr) { + target->focus(); + while (target->parent != nullptr) target = target->parent; + target->recalcSizePosRecursive(); } } @@ -1501,8 +1085,8 @@ Hy3Node* findTabBarAt(Hy3Node& node, Vector2D pos, Hy3Node** focused_node) { auto& children = node.data.as_group.children; auto& tab_bar = *node.data.as_group.tab_bar; - auto size = tab_bar.size.vec(); - auto x = pos.x - tab_bar.pos.vec().x; + auto size = tab_bar.size.value(); + auto x = pos.x - tab_bar.pos.value().x; auto child_iter = children.begin(); for (auto& tab: tab_bar.bar.entries) { @@ -1734,7 +1318,7 @@ fullscreen: // goto fsupdate; fsupdate: g_pCompositor->updateWindowAnimatedDecorationValues(window); - g_pXWaylandManager->setWindowSize(window, window->m_vRealSize.goalv()); + g_pXWaylandManager->setWindowSize(window, window->m_vRealSize.goal()); g_pCompositor->changeWindowZOrder(window, true); this->recalculateMonitor(monitor->ID); } @@ -1754,7 +1338,7 @@ bool Hy3Layout::shouldRenderSelected(CWindow* window) { case Hy3NodeType::Group: { auto* node = this->getNodeFromWindow(window); if (node == nullptr) return false; - return focused->hasChild(node); + return focused->data.as_group.hasChild(node); } default: return false; } @@ -1888,7 +1472,7 @@ void Hy3Layout::applyNodeDataToWindow(Hy3Node* node, bool no_animation) { "node {:x}'s workspace has no associated monitor, cannot apply node data", (uintptr_t) node ); - //errorNotif(); + errorNotif(); return; } @@ -1985,6 +1569,19 @@ void Hy3Layout::applyNodeDataToWindow(Hy3Node* node, bool no_animation) { } } +bool shiftIsForward(ShiftDirection direction) { + return direction == ShiftDirection::Right || direction == ShiftDirection::Down; +} + +bool shiftIsVertical(ShiftDirection direction) { + return direction == ShiftDirection::Up || direction == ShiftDirection::Down; +} + +bool shiftMatchesLayout(Hy3GroupLayout layout, ShiftDirection direction) { + return (layout == Hy3GroupLayout::SplitV && shiftIsVertical(direction)) + || (layout != Hy3GroupLayout::SplitV && !shiftIsVertical(direction)); +} + Hy3Node* Hy3Layout::shiftOrGetFocus( Hy3Node& node, ShiftDirection direction, @@ -2067,14 +1664,10 @@ Hy3Node* Hy3Layout::shiftOrGetFocus( std::list::iterator insert; if (break_origin == parent_group.children.front() && !shiftIsForward(direction)) { - if (!shift) { - return nullptr; - } + if (!shift) return nullptr; insert = parent_group.children.begin(); } else if (break_origin == parent_group.children.back() && shiftIsForward(direction)) { - if (!shift) { - return nullptr; - } + if (!shift) return nullptr; insert = parent_group.children.end(); } else { auto& group_data = target_group->data.as_group; @@ -2096,19 +1689,14 @@ Hy3Node* Hy3Layout::shiftOrGetFocus( if (shiftIsForward(direction)) insert = iter; else insert = std::next(iter); } - } else { - return (*iter)->getFocusedNode(); - } + } else return (*iter)->getFocusedNode(); } else { // break into neighboring groups until we hit a window while (true) { target_group = *iter; auto& group_data = target_group->data.as_group; - if (group_data.children.empty()) { - // in theory this would never happen - return nullptr; - } + if (group_data.children.empty()) return nullptr; // in theory this would never happen bool shift_after = false; @@ -2194,7 +1782,7 @@ Hy3Node* Hy3Layout::shiftOrGetFocus( if (old_parent != nullptr) { auto& group = old_parent->data.as_group; if (old_parent->parent != nullptr && group.ephemeral && group.children.size() == 1 - && !old_parent->hasChild(&node)) + && !group.hasChild(&node)) { Hy3Node::swallowGroups(old_parent); } diff --git a/src/Hy3Layout.hpp b/src/Hy3Layout.hpp index 7ba19c3..766d0bb 100644 --- a/src/Hy3Layout.hpp +++ b/src/Hy3Layout.hpp @@ -1,11 +1,4 @@ #pragma once -#include -#include -#include - -#include - -#include "BitFlag.hpp" class Hy3Layout; @@ -15,6 +8,11 @@ enum class GroupEphemeralityOption { ForceEphemeral, }; +#include +#include + +#include + enum class ShiftDirection { Left, Up, @@ -22,19 +20,10 @@ enum class ShiftDirection { Right, }; -enum class SearchDirection { None, Forwards, Backwards }; - enum class Axis { None, Horizontal, Vertical }; -enum class Layer { None = 0, Tiled = 1 << 0, Floating = 1 << 1 }; - -inline Layer operator|(Layer a, Layer b) { return static_cast((int) a | (int) b); } - -inline Layer operator&(Layer a, Layer b) { return static_cast((int) a & (int) b); } - #include "Hy3Node.hpp" #include "TabGroup.hpp" -#include "conversions.hpp" enum class FocusShift { Top, @@ -78,31 +67,11 @@ enum class ExpandFullscreenOption { MaximizeAsFullscreen, }; -struct FocusOverride { - Hy3Node* left = nullptr; - Hy3Node* up = nullptr; - Hy3Node* right = nullptr; - Hy3Node* down = nullptr; - - Hy3Node** forDirection(ShiftDirection direction) { - switch (direction) { - case ShiftDirection::Left: return &left; - case ShiftDirection::Up: return &up; - case ShiftDirection::Right: return &right; - case ShiftDirection::Down: return &down; - default: UNREACHABLE(); - } - } - - bool isEmpty() { return !(left || right || up || down); } -}; - 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 onWindowRemovedFloating(CWindow*); virtual void onWindowFocusChange(CWindow*); virtual bool isWindowTiled(CWindow*); virtual void recalculateMonitor(const int& monitor_id); @@ -141,14 +110,13 @@ public: void changeGroupEphemeralityOn(Hy3Node&, bool ephemeral); void shiftNode(Hy3Node&, ShiftDirection, bool once, bool visible); void shiftWindow(int workspace, ShiftDirection, bool once, bool visible); - void shiftFocus(int workspace, ShiftDirection, bool visible, BitFlag = Layer::None); + void shiftFocus(int workspace, ShiftDirection, bool visible); void moveNodeToWorkspace(int origin, std::string wsname, bool follow); void changeFocus(int workspace, FocusShift); void focusTab(int workspace, TabFocus target, TabFocusMousePriority, bool wrap_scroll, int index); void setNodeSwallow(int workspace, SetSwallowOption); void killFocusedNode(int workspace); void expand(int workspace, ExpandOption, ExpandFullscreenOption); - void resizeNode(const Vector2D& delta, eRectCorner corner, Hy3Node* node); bool shouldRenderSelected(CWindow*); @@ -170,10 +138,6 @@ public: private: Hy3Node* getNodeFromWindow(CWindow*); void applyNodeDataToWindow(Hy3Node*, bool no_animation = false); - void shiftFocusToMonitor(ShiftDirection direction); - std::unordered_map m_focusIntercepts; - Hy3Node* getFocusOverride(CWindow* src, ShiftDirection direction); - void setFocusOverride(CWindow* src, ShiftDirection direction, Hy3Node* dest); // if shift is true, shift the window in the given direction, returning // nullptr, if shift is false, return the window in the given direction or @@ -183,7 +147,6 @@ private: void updateAutotileWorkspaces(); bool shouldAutotileWorkspace(int); void resizeNode(Hy3Node*, Vector2D, ShiftDirection resize_edge_x, ShiftDirection resize_edge_y); - void focusMonitor(CMonitor*); struct { std::string raw_workspaces; diff --git a/src/Hy3Node.cpp b/src/Hy3Node.cpp index d61fa72..5eed0fc 100644 --- a/src/Hy3Node.cpp +++ b/src/Hy3Node.cpp @@ -1,4 +1,3 @@ -#include #include #include @@ -34,6 +33,18 @@ Hy3GroupData::~Hy3GroupData() { if (this->tab_bar != nullptr) this->tab_bar->bar.beginDestroy(); } +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; + } + } + + return false; +} + void Hy3GroupData::collapseExpansions() { if (this->expand_focused == ExpandFocusType::NotExpanded) return; this->expand_focused = ExpandFocusType::NotExpanded; @@ -184,17 +195,20 @@ void markGroupFocusedRecursive(Hy3GroupData& group) { void Hy3Node::markFocused() { Hy3Node* node = this; + // undo decos for root focus + auto* root = node; + while (root->parent != nullptr) root = root->parent; + // update focus if (this->data.type == Hy3NodeType::Group) { markGroupFocusedRecursive(this->data.as_group); } - // undo decos for root focus - auto* root = node; - while (root->parent != nullptr) { - root->parent->data.as_group.focused_child = root; - root->parent->data.as_group.group_focused = false; - root = root->parent; + auto* node2 = node; + while (node2->parent != nullptr) { + node2->parent->data.as_group.focused_child = node2; + node2->parent->data.as_group.group_focused = false; + node2 = node2->parent; } root->updateDecos(); @@ -828,6 +842,24 @@ Hy3Node* Hy3Node::getImmediateSibling(ShiftDirection direction) { return *list_sibling; } +Axis getAxis(Hy3GroupLayout layout) { + switch (layout) { + case Hy3GroupLayout::SplitH: return Axis::Horizontal; + case Hy3GroupLayout::SplitV: return Axis::Vertical; + default: return Axis::None; + } +} + +Axis getAxis(ShiftDirection direction) { + switch (direction) { + case ShiftDirection::Left: + case ShiftDirection::Right: return Axis::Horizontal; + case ShiftDirection::Down: + case ShiftDirection::Up: return Axis::Vertical; + default: return Axis::None; + } +} + Hy3Node* Hy3Node::findNeighbor(ShiftDirection direction) { auto current_node = this; Hy3Node* sibling = nullptr; @@ -862,8 +894,6 @@ int directionToIteratorIncrement(ShiftDirection direction) { } } -Vector2D Hy3Node::middle() { return this->position + this->size / 2.f; } - void Hy3Node::resize(ShiftDirection direction, double delta, bool no_animation) { auto& parent_node = this->parent; auto& containing_group = parent_node->data.as_group; @@ -896,13 +926,6 @@ void Hy3Node::resize(ShiftDirection direction, double delta, bool no_animation) neighbor->size_ratio = requested_neighbor_size_ratio; parent_node->recalcSizePosRecursive(no_animation); - } else { - hy3_log( - WARN, - "Requested size ratio {} or {} out of bounds, ignoring", - requested_size_ratio, - requested_neighbor_size_ratio - ); } } } @@ -926,19 +949,3 @@ void Hy3Node::swapData(Hy3Node& a, Hy3Node& b) { } } } - -bool Hy3Node::hasChild(Hy3Node* node) { - if (this->data.type == Hy3NodeType::Window) return false; - - auto n = node; - while (n != nullptr && n->parent != this) n = n->parent; - - return n != nullptr; -} - -Hy3Node* Hy3Node::getRoot() { - Hy3Node* maybeRoot = this; - while (maybeRoot->parent) maybeRoot = maybeRoot->parent; - - return maybeRoot; -} \ No newline at end of file diff --git a/src/Hy3Node.hpp b/src/Hy3Node.hpp index 651c763..f892efb 100644 --- a/src/Hy3Node.hpp +++ b/src/Hy3Node.hpp @@ -10,7 +10,6 @@ enum class Hy3GroupLayout; #include "Hy3Layout.hpp" #include "TabGroup.hpp" -#include "conversions.hpp" enum class Hy3GroupLayout { SplitH, @@ -43,6 +42,7 @@ struct Hy3GroupData { Hy3GroupData(Hy3GroupLayout layout); ~Hy3GroupData(); + bool hasChild(Hy3Node* child); void collapseExpansions(); void setLayout(Hy3GroupLayout layout); void setEphemeral(GroupEphemeralityOption ephemeral); @@ -98,11 +98,9 @@ struct Hy3Node { CWindow* bringToTop(); void markFocused(); void raiseToTop(); - Vector2D middle(); Hy3Node* getFocusedNode(bool ignore_group_focus = false, bool stop_at_expanded = false); Hy3Node* findNeighbor(ShiftDirection); Hy3Node* getImmediateSibling(ShiftDirection); - Hy3Node* getRoot(); void resize(ShiftDirection, double, bool no_animation = false); bool isIndirectlyFocused(); Hy3Node& getExpandActor(); @@ -118,7 +116,6 @@ struct Hy3Node { Hy3Node* findNodeForTabGroup(Hy3TabGroup&); void appendAllWindows(std::vector&); - bool hasChild(Hy3Node* child); std::string debugNode(); // Remove this node from its parent, deleting the parent if it was @@ -134,39 +131,3 @@ struct Hy3Node { static bool swallowGroups(Hy3Node* into); static void swapData(Hy3Node&, Hy3Node&); }; - -struct Distance { - double primary_axis; - double secondary_axis; - - Distance() = default; - - Distance(ShiftDirection direction, Vector2D from, Vector2D to) { - auto dist = from - to; - primary_axis = getAxis(direction) == Axis::Horizontal ? dist.x : dist.y; - secondary_axis = getAxis(direction) == Axis::Horizontal ? dist.y : dist.x; - } - - bool operator<(Distance other) { - return signbit(primary_axis) == signbit(other.primary_axis) - && (abs(primary_axis) < abs(other.primary_axis) - || (primary_axis == other.primary_axis - && abs(secondary_axis) < abs(other.secondary_axis))); - } - - bool operator>(Distance other) { - return signbit(primary_axis) == signbit(other.primary_axis) - && (abs(primary_axis) > abs(other.primary_axis) - || (primary_axis == other.primary_axis - && abs(secondary_axis) > abs(other.secondary_axis))); - } - - bool isSameDirection(Distance other) { - return signbit(primary_axis) == signbit(other.primary_axis); - } - - bool isInDirection(ShiftDirection direction) { - return std::signbit(primary_axis) - == (getSearchDirection(direction) == SearchDirection::Forwards); - } -}; \ No newline at end of file diff --git a/src/TabGroup.cpp b/src/TabGroup.cpp index 5853b85..5483683 100644 --- a/src/TabGroup.cpp +++ b/src/TabGroup.cpp @@ -12,7 +12,6 @@ Hy3TabBarEntry::Hy3TabBarEntry(Hy3TabBar& tab_bar, Hy3Node& node): tab_bar(tab_bar), node(node) { this->focused.create( - AVARTYPE_FLOAT, 0.0f, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), nullptr, @@ -20,7 +19,6 @@ Hy3TabBarEntry::Hy3TabBarEntry(Hy3TabBar& tab_bar, Hy3Node& node): tab_bar(tab_b ); this->urgent.create( - AVARTYPE_FLOAT, 0.0f, g_pConfigManager->getAnimationPropertyConfig("fadeSwitch"), nullptr, @@ -28,7 +26,6 @@ Hy3TabBarEntry::Hy3TabBarEntry(Hy3TabBar& tab_bar, Hy3Node& node): tab_bar(tab_b ); this->offset.create( - AVARTYPE_FLOAT, -1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), nullptr, @@ -36,7 +33,6 @@ Hy3TabBarEntry::Hy3TabBarEntry(Hy3TabBar& tab_bar, Hy3Node& node): tab_bar(tab_b ); this->width.create( - AVARTYPE_FLOAT, -1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), nullptr, @@ -44,7 +40,6 @@ Hy3TabBarEntry::Hy3TabBarEntry(Hy3TabBar& tab_bar, Hy3Node& node): tab_bar(tab_b ); this->vertical_pos.create( - AVARTYPE_FLOAT, 1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), nullptr, @@ -52,7 +47,6 @@ Hy3TabBarEntry::Hy3TabBarEntry(Hy3TabBar& tab_bar, Hy3Node& node): tab_bar(tab_b ); this->fade_opacity.create( - AVARTYPE_FLOAT, 0.0f, g_pConfigManager->getAnimationPropertyConfig("windowsIn"), nullptr, @@ -89,14 +83,14 @@ bool Hy3TabBarEntry::operator==(const Hy3TabBarEntry& entry) const { } void Hy3TabBarEntry::setFocused(bool focused) { - if (this->focused.goalf() != focused) { + if (this->focused.goal() != focused) { this->focused = focused; } } void Hy3TabBarEntry::setUrgent(bool urgent) { - if (urgent && this->focused.goalf() == 1.0) urgent = false; - if (this->urgent.goalf() != urgent) { + if (urgent && this->focused.goal() == 1.0) urgent = false; + if (this->urgent.goal() != urgent) { this->urgent = urgent; } } @@ -121,7 +115,7 @@ void Hy3TabBarEntry::unDestroy() { } bool Hy3TabBarEntry::shouldRemove() { - return this->destroying && (this->vertical_pos.fl() == 1.0 || this->width.fl() == 0.0); + return this->destroying && (this->vertical_pos.value() == 1.0 || this->width.value() == 0.0); } void Hy3TabBarEntry::prepareTexture(float scale, CBox& box) { @@ -149,8 +143,8 @@ void Hy3TabBarEntry::prepareTexture(float scale, CBox& box) { // clang-format off || this->last_render.x != box.x || this->last_render.y != box.y - || this->last_render.focused != this->focused.fl() - || this->last_render.urgent != this->urgent.fl() + || this->last_render.focused != this->focused.value() + || this->last_render.urgent != this->urgent.value() || this->last_render.window_title != this->window_title || this->last_render.rounding != rounding || this->last_render.text_font != *text_font @@ -167,8 +161,8 @@ void Hy3TabBarEntry::prepareTexture(float scale, CBox& box) { { this->last_render.x = box.x; this->last_render.y = box.y; - this->last_render.focused = this->focused.fl(); - this->last_render.urgent = this->urgent.fl(); + this->last_render.focused = this->focused.value(); + this->last_render.urgent = this->urgent.value(); this->last_render.window_title = this->window_title; this->last_render.rounding = rounding; this->last_render.text_font = *text_font; @@ -191,8 +185,8 @@ void Hy3TabBarEntry::prepareTexture(float scale, CBox& box) { cairo_restore(cairo); // set brush - auto focused = this->focused.fl(); - auto urgent = this->urgent.fl(); + auto focused = this->focused.value(); + auto urgent = this->urgent.value(); auto inactive = 1.0 - (focused + urgent); auto c = (CColor(*col_active) * focused) + (CColor(*col_urgent) * urgent) + (CColor(*col_inactive) * inactive); @@ -278,7 +272,6 @@ void Hy3TabBarEntry::prepareTexture(float scale, CBox& box) { Hy3TabBar::Hy3TabBar() { this->fade_opacity.create( - AVARTYPE_FLOAT, 1.0f, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), nullptr, @@ -405,21 +398,21 @@ void Hy3TabBar::updateAnimations(bool warp) { entry->offset.setValueAndWarp(offset); entry->width.setValueAndWarp(entry_width); } else { - auto warp_init = entry->offset.goalf() == -1.0; + auto warp_init = entry->offset.goal() == -1.0; if (warp_init) { entry->offset.setValueAndWarp(offset); - entry->width.setValueAndWarp(entry->vertical_pos.fl() == 0.0 ? 0.0 : entry_width); + entry->width.setValueAndWarp(entry->vertical_pos.value() == 0.0 ? 0.0 : entry_width); } if (!entry->destroying) { - if (entry->offset.goalf() != offset) entry->offset = offset; - if ((warp_init || entry->width.goalf() != 0.0) && entry->width.goalf() != entry_width) + if (entry->offset.goal() != offset) entry->offset = offset; + if ((warp_init || entry->width.goal() != 0.0) && entry->width.goal() != entry_width) entry->width = entry_width; } } - if (!entry->destroying) offset += entry->width.goalf(); + if (!entry->destroying) offset += entry->width.goal(); entry = std::next(entry); } } @@ -431,14 +424,12 @@ void Hy3TabBar::setSize(Vector2D size) { Hy3TabGroup::Hy3TabGroup(Hy3Node& node) { this->pos.create( - AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), nullptr, AVARDAMAGE_NONE ); this->size.create( - AVARTYPE_VECTOR, g_pConfigManager->getAnimationPropertyConfig("windowsMove"), nullptr, AVARDAMAGE_NONE @@ -468,12 +459,12 @@ void Hy3TabGroup::updateWithGroup(Hy3Node& node, bool warp) { // clang-format on this->hidden = node.hidden; - if (this->pos.goalv() != tpos) { + if (this->pos.goal() != tpos) { this->pos = tpos; if (warp) this->pos.warp(); } - if (this->size.goalv() != tsize) { + if (this->size.goal() != tsize) { this->size = tsize; if (warp) this->size.warp(); } @@ -495,14 +486,14 @@ void Hy3TabGroup::tick() { if (workspace != nullptr) { if (workspace->m_bHasFullscreenWindow) { - if (this->bar.fade_opacity.goalf() != 0.0) this->bar.fade_opacity = 0.0; + if (this->bar.fade_opacity.goal() != 0.0) this->bar.fade_opacity = 0.0; } else { - if (this->bar.fade_opacity.goalf() != 1.0) this->bar.fade_opacity = 1.0; + if (this->bar.fade_opacity.goal() != 1.0) this->bar.fade_opacity = 1.0; } } - auto pos = this->pos.vec(); - auto size = this->size.vec(); + auto pos = this->pos.value(); + auto size = this->size.value(); if (this->last_pos != pos || this->last_size != size) { CBox damage_box = {this->last_pos.x, this->last_pos.y, this->last_size.x, this->last_size.y}; @@ -538,11 +529,11 @@ void Hy3TabGroup::renderTabBar() { auto scale = monitor->scale; auto monitor_size = monitor->vecSize; - auto pos = this->pos.vec() - monitor->vecPosition; - auto size = this->size.vec(); + auto pos = this->pos.value() - monitor->vecPosition; + auto size = this->size.value(); if (workspace != nullptr) { - pos = pos + workspace->m_vRenderOffset.vec(); + pos = pos + workspace->m_vRenderOffset.value(); } auto scaled_pos = Vector2D(std::round(pos.x * scale), std::round(pos.y * scale)); @@ -589,8 +580,8 @@ void Hy3TabGroup::renderTabBar() { for (auto* window: this->stencil_windows) { if (!g_pCompositor->windowExists(window)) continue; - auto wpos = window->m_vRealPosition.vec() - monitor->vecPosition; - auto wsize = window->m_vRealSize.vec(); + auto wpos = window->m_vRealPosition.value() - monitor->vecPosition; + auto wsize = window->m_vRealSize.value(); CBox window_box = {wpos.x, wpos.y, wsize.x, wsize.y}; // scaleBox(&window_box, scale); @@ -608,16 +599,16 @@ void Hy3TabGroup::renderTabBar() { } auto fade_opacity = - this->bar.fade_opacity.fl() * (workspace == nullptr ? 1.0 : workspace->m_fAlpha.fl()); + this->bar.fade_opacity.value() * (workspace == nullptr ? 1.0 : workspace->m_fAlpha.value()); auto render_entry = [&](Hy3TabBarEntry& entry) { Vector2D entry_pos = { - (pos.x + (entry.offset.fl() * size.x) + (*padding * 0.5)) * scale, + (pos.x + (entry.offset.value() * size.x) + (*padding * 0.5)) * scale, scaled_pos.y + ((entry.vertical_pos.value() * (size.y + *padding) * scale) * (*enter_from_top ? -1 : 1)), }; - Vector2D entry_size = {((entry.width.fl() * size.x) - *padding) * scale, scaled_size.y}; + Vector2D entry_size = {((entry.width.value() * size.x) - *padding) * scale, scaled_size.y}; if (entry_size.x < 0 || entry_size.y < 0 || fade_opacity == 0.0) return; CBox box = { @@ -628,16 +619,16 @@ void Hy3TabGroup::renderTabBar() { }; entry.prepareTexture(scale, box); - g_pHyprOpenGL->renderTexture(entry.texture, &box, fade_opacity * entry.fade_opacity.fl()); + g_pHyprOpenGL->renderTexture(entry.texture, &box, fade_opacity * entry.fade_opacity.value()); }; for (auto& entry: this->bar.entries) { - if (entry.focused.goalf() == 1.0) continue; + if (entry.focused.goal() == 1.0) continue; render_entry(entry); } for (auto& entry: this->bar.entries) { - if (entry.focused.goalf() == 0.0) continue; + if (entry.focused.goal() == 0.0) continue; render_entry(entry); } @@ -678,6 +669,5 @@ void findOverlappingWindows(Hy3Node& node, float height, std::vector& void Hy3TabGroup::updateStencilWindows(Hy3Node& group) { this->stencil_windows.clear(); - findOverlappingWindows(group, this->size.goalv().y, this->stencil_windows); + findOverlappingWindows(group, this->size.goal().y, this->stencil_windows); } - diff --git a/src/TabGroup.hpp b/src/TabGroup.hpp index 6cf92c7..77f7874 100644 --- a/src/TabGroup.hpp +++ b/src/TabGroup.hpp @@ -16,12 +16,12 @@ struct Hy3TabBarEntry { std::string window_title; bool destroying = false; CTexture texture; - CAnimatedVariable focused; - CAnimatedVariable urgent; - CAnimatedVariable offset; // 0.0-1.0 of total bar - CAnimatedVariable width; // 0.0-1.0 of total bar - CAnimatedVariable vertical_pos; // 0.0-1.0, user specified direction - CAnimatedVariable fade_opacity; // 0.0-1.0 + CAnimatedVariable focused; + CAnimatedVariable urgent; + CAnimatedVariable offset; // 0.0-1.0 of total bar + CAnimatedVariable width; // 0.0-1.0 of total bar + CAnimatedVariable vertical_pos; // 0.0-1.0, user specified direction + CAnimatedVariable fade_opacity; // 0.0-1.0 Hy3TabBar& tab_bar; Hy3Node& node; // only used for comparioson. do not deref. @@ -62,7 +62,7 @@ public: bool destroy = false; bool dirty = true; bool damaged = true; - CAnimatedVariable fade_opacity; + CAnimatedVariable fade_opacity; Hy3TabBar(); void beginDestroy(); @@ -89,8 +89,8 @@ public: int workspace_id = -1; bool hidden = false; Hy3TabBar bar; - CAnimatedVariable pos; - CAnimatedVariable size; + CAnimatedVariable pos; + CAnimatedVariable size; // initialize a group with the given node. UB if node is not a group. Hy3TabGroup(Hy3Node&); diff --git a/src/conversions.cpp b/src/conversions.cpp deleted file mode 100644 index 46785b3..0000000 --- a/src/conversions.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "Hy3Node.hpp" - -Axis getAxis(Hy3GroupLayout layout) { - switch (layout) { - case Hy3GroupLayout::SplitH: return Axis::Horizontal; - case Hy3GroupLayout::SplitV: return Axis::Vertical; - default: return Axis::None; - } -} - -Axis getAxis(ShiftDirection direction) { - switch (direction) { - case ShiftDirection::Left: - case ShiftDirection::Right: return Axis::Horizontal; - case ShiftDirection::Down: - case ShiftDirection::Up: return Axis::Vertical; - default: return Axis::None; - } -} - -SearchDirection getSearchDirection(ShiftDirection direction) { - switch (direction) { - case ShiftDirection::Left: - case ShiftDirection::Up: return SearchDirection::Backwards; - case ShiftDirection::Right: - case ShiftDirection::Down: return SearchDirection::Forwards; - default: return SearchDirection::None; - } -} - -char directionToChar(ShiftDirection direction) { - switch (direction) { - case ShiftDirection::Left: return 'l'; - case ShiftDirection::Up: return 'u'; - case ShiftDirection::Down: return 'd'; - case ShiftDirection::Right: return 'r'; - default: return 'r'; - } -} diff --git a/src/conversions.hpp b/src/conversions.hpp deleted file mode 100644 index 96f1c70..0000000 --- a/src/conversions.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "Hy3Node.hpp" - -Axis getAxis(Hy3GroupLayout); -Axis getAxis(ShiftDirection); -SearchDirection getSearchDirection(ShiftDirection); -char directionToChar(ShiftDirection); diff --git a/src/dispatchers.cpp b/src/dispatchers.cpp index a69a390..667b1cf 100644 --- a/src/dispatchers.cpp +++ b/src/dispatchers.cpp @@ -8,10 +8,8 @@ int workspace_for_action(bool allow_fullscreen = false) { if (g_pLayoutManager->getCurrentLayout() != g_Hy3Layout.get()) return -1; - if (!g_pCompositor->m_pLastMonitor) return -1; - int workspace_id = g_pCompositor->m_pLastMonitor->specialWorkspaceID; - if (workspace_id == 0) workspace_id = g_pCompositor->m_pLastMonitor->activeWorkspace; + int workspace_id = g_pCompositor->m_pLastMonitor->activeWorkspace; if (workspace_id == -1) return -1; auto* workspace = g_pCompositor->getWorkspaceByID(workspace_id); @@ -85,14 +83,6 @@ std::optional parseShiftArg(std::string arg) { else return {}; } -std::optional> parseLayerArg(std::string arg) { - if (arg == "same" || arg == "samelayer") return Layer::None; - else if (arg == "tiled") return Layer::Tiled; - else if (arg == "floating") return Layer::Floating; - else if (arg == "all" || arg == "any") return Layer::Tiled | Layer::Floating; - else return {}; -} - void dispatch_movewindow(std::string value) { int workspace = workspace_for_action(); if (workspace == -1) return; @@ -123,24 +113,9 @@ void dispatch_movefocus(std::string value) { if (workspace == -1) return; auto args = CVarList(value); - std::optional> layerArg; if (auto shift = parseShiftArg(args[0])) { - bool visible; - BitFlag layers; - - for (auto arg: args) { - if (arg == "visible") visible = true; - else if ((layerArg = parseLayerArg(arg))) layers |= layerArg.value(); - } - - if (!layerArg) { - const static auto default_movefocus_layer = - ConfigValue("plugin:hy3:default_movefocus_layer"); - if ((layerArg = parseLayerArg(*default_movefocus_layer))) layers |= layerArg.value(); - } - - g_Hy3Layout->shiftFocus(workspace, shift.value(), visible, layers); + g_Hy3Layout->shiftFocus(workspace, shift.value(), args[1] == "visible"); } } @@ -263,26 +238,14 @@ void dispatch_debug(std::string arg) { if (workspace == -1) return; auto* root = g_Hy3Layout->getWorkspaceRootGroup(workspace); - if (root == nullptr) { + if (workspace == -1) { hy3_log(LOG, "DEBUG NODES: no nodes on workspace"); } else { hy3_log(LOG, "DEBUG NODES\n{}", root->debugNode().c_str()); } } -void dispatch_resizenode(std::string value) { - int workspace = workspace_for_action(); - if (workspace == -1) return; - - auto* node = g_Hy3Layout->getWorkspaceFocusedNode(workspace, false, true); - const auto delta = g_pCompositor->parseWindowVectorArgsRelative(value, Vector2D(0, 0)); - - hy3_log(LOG, "resizeNode: node: {:x}, delta: {:X}", (uintptr_t) node, delta); - g_Hy3Layout->resizeNode(delta, CORNER_NONE, node); -} - void registerDispatchers() { - HyprlandAPI::addDispatcher(PHANDLE, "hy3:resizenode", dispatch_resizenode); HyprlandAPI::addDispatcher(PHANDLE, "hy3:makegroup", dispatch_makegroup); HyprlandAPI::addDispatcher(PHANDLE, "hy3:changegroup", dispatch_changegroup); HyprlandAPI::addDispatcher(PHANDLE, "hy3:setephemeral", dispatch_setephemeral); diff --git a/src/main.cpp b/src/main.cpp index 9c48e0a..ec90526 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -39,9 +39,6 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { CONF("group_inset", INT, 10); CONF("special_scale_factor", FLOAT, 0.8); CONF("tab_first_window", INT, 0); - CONF("kbd_shift_delta", INT, 20); - CONF("default_movefocus_layer", STRING, "samelayer"); - CONF("focus_obscured_windows_policy", INT, 2); // tabs CONF("tabs:height", INT, 15); @@ -80,4 +77,3 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { } APICALL EXPORT void PLUGIN_EXIT() {} -