diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp index 981a2f2..e26a054 100644 --- a/src/Hy3Layout.cpp +++ b/src/Hy3Layout.cpp @@ -698,7 +698,7 @@ CWindow* Hy3Layout::getNextWindowCandidate(CWindow* window) { // return the first floating window on the same workspace that has not asked not to be focused if (window->m_bIsFloating) { - for (std::unique_ptr& w: g_pCompositor->m_vWindows | std::views::reverse) { + for (auto& w: g_pCompositor->m_vWindows | std::views::reverse) { if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 && w->m_iWorkspaceID == window->m_iWorkspaceID && !w->m_bX11ShouldntFocus && !w->m_bNoFocus && w.get() != window) @@ -937,10 +937,53 @@ void Hy3Layout::shiftWindow(int workspace, ShiftDirection direction, bool once, } void Hy3Layout::shiftFocus(int workspace, ShiftDirection direction, bool visible) { + auto* current_window = g_pCompositor->m_pLastWindow; + auto* p_workspace = g_pCompositor->getWorkspaceByID(current_window->m_iWorkspaceID); + if (p_workspace->m_bHasFullscreenWindow) return; + + if (current_window != nullptr && current_window->m_bIsFloating) { + CWindow* next_window = nullptr; + double next_distance = -1; + + for (auto& w: g_pCompositor->m_vWindows) { + if (w->m_bIsMapped && !w->isHidden() && w->m_bIsFloating && w->m_iX11Type != 2 + && w->m_iWorkspaceID == current_window->m_iWorkspaceID && !w->m_bX11ShouldntFocus + && !w->m_bNoFocus && w.get() != current_window) + { + double distance = 0; + + auto cpos = current_window->m_vRealPosition.vec() + (current_window->m_vRealSize.vec() / 2); + auto tpos = w->m_vRealPosition.vec() + (w->m_vRealSize.vec() / 2); + + auto x_offset = tpos.x - cpos.x; + auto y_offset = tpos.y - cpos.y; + + if (abs(x_offset) > abs(y_offset)) { + if (x_offset < 0 && direction == ShiftDirection::Left) distance = -x_offset; + else if (x_offset > 0 && direction == ShiftDirection::Right) distance = x_offset; + } else { + if (y_offset < 0 && direction == ShiftDirection::Up) distance = -y_offset; + else if (y_offset > 0 && direction == ShiftDirection::Down) distance = y_offset; + } + + if (distance <= 0) continue; + + if (next_distance == -1 || distance < next_distance) { + next_window = w.get(); + next_distance = distance; + } + } + } + + if (next_window != nullptr) g_pCompositor->focusWindow(next_window); + return; + } + auto* node = this->getWorkspaceFocusedNode(workspace); if (node == nullptr) return; auto* target = this->shiftOrGetFocus(*node, direction, false, false, visible); + if (target != nullptr) { target->focus(); while (target->parent != nullptr) target = target->parent;