* @brief Starts a brief focus-ripple across all registered tiles in visual order. */
| 769 | * @brief Starts a brief focus-ripple across all registered tiles in visual order. |
| 770 | */ |
| 771 | void UI::Taskbar::startFocusCycle() |
| 772 | { |
| 773 | m_focusCycleTimer.stop(); |
| 774 | m_focusCycleQueue.clear(); |
| 775 | |
| 776 | if (!m_windowManager) |
| 777 | return; |
| 778 | |
| 779 | const auto& order = m_windowManager->windowOrder(); |
| 780 | for (int id : order) |
| 781 | if (auto* win = windowData(id)) |
| 782 | m_focusCycleQueue.append(win); |
| 783 | |
| 784 | if (m_focusCycleQueue.isEmpty()) |
| 785 | return; |
| 786 | |
| 787 | if (m_focusCycleQueue.size() == 1) { |
| 788 | QQuickItem* only = m_focusCycleQueue.first(); |
| 789 | m_focusCycleQueue.clear(); |
| 790 | setActiveWindow(only); |
| 791 | return; |
| 792 | } |
| 793 | |
| 794 | QQuickItem* firstTile = m_focusCycleQueue.first(); |
| 795 | m_focusCycleQueue.append(firstTile); |
| 796 | |
| 797 | constexpr int kBudgetMs = 200; |
| 798 | constexpr int kMinMs = 10; |
| 799 | constexpr int kMaxMs = 40; |
| 800 | const int interval = qBound(kMinMs, kBudgetMs / m_focusCycleQueue.size(), kMaxMs); |
| 801 | m_focusCycleTimer.setInterval(interval); |
| 802 | m_focusCycleTimer.start(); |
| 803 | } |
| 804 | |
| 805 | /** |
| 806 | * @brief Advances the focus-cycle by one tile, stopping when the queue drains. |