Skip to content

Commit

Permalink
feat: cyclehist dispatcher
Browse files Browse the repository at this point in the history
  • Loading branch information
Крылов Александр authored and Alexandr Krylov committed Jan 22, 2025
1 parent ce48bc5 commit 46cad0e
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 46 deletions.
67 changes: 40 additions & 27 deletions src/Compositor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,20 @@
#include "managers/VersionKeeperManager.hpp"
#include "managers/DonationNagManager.hpp"
#include "managers/eventLoop/EventLoopManager.hpp"
#include <algorithm>
#include <aquamarine/output/Output.hpp>
#include <bit>
#include <ctime>
#include <random>
#include <print>
#include <cstring>
#include <filesystem>
#include <ranges>
#include <unordered_set>
#include "debug/HyprCtl.hpp"
#include "debug/CrashReporter.hpp"
#ifdef USES_SYSTEMD
#include <helpers/SdDaemon.hpp> // for SdNotify
#endif
#include <ranges>
#include "helpers/varlist/VarList.hpp"
#include "helpers/fs/FsUtils.hpp"
#include "protocols/FractionalScale.hpp"
Expand All @@ -44,7 +43,6 @@
#include "xwayland/XWayland.hpp"
#include "helpers/ByteOperations.hpp"
#include "render/decorations/CHyprGroupBarDecoration.hpp"

#include "managers/KeybindManager.hpp"
#include "managers/SessionLockManager.hpp"
#include "managers/XWaylandManager.hpp"
Expand Down Expand Up @@ -1640,37 +1638,51 @@ PHLWINDOW CCompositor::getWindowInDirection(const CBox& box, PHLWORKSPACE pWorks
return nullptr;
}

PHLWINDOW CCompositor::getNextWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional<bool> floating, bool visible) {
auto it = std::ranges::find(m_vWindows, pWindow);
const auto FINDER = [&](const PHLWINDOW& w) { return isWindowAvailableForCycle(pWindow, w, focusableOnly, floating, visible); };
const auto IN_RIGHT = std::find_if(it, m_vWindows.end(), FINDER);
if (IN_RIGHT != m_vWindows.end())
return *IN_RIGHT;
const auto IN_LEFT = std::find_if(m_vWindows.begin(), it, FINDER);
return *IN_LEFT;
template <typename WINDOWPTR>
static bool isWorkspaceMatches(WINDOWPTR pWindow, const WINDOWPTR w, bool anyWorkspace) {
return anyWorkspace ? w->m_pWorkspace && w->m_pWorkspace->isVisible() : w->m_pWorkspace == pWindow->m_pWorkspace;
}

PHLWINDOW CCompositor::getPrevWindowOnWorkspace(PHLWINDOW pWindow, bool focusableOnly, std::optional<bool> floating, bool visible) {
auto it = std::ranges::find(std::ranges::reverse_view(m_vWindows), pWindow);
const auto FINDER = [&](const PHLWINDOW& w) { return isWindowAvailableForCycle(pWindow, w, focusableOnly, floating, visible); };
const auto IN_LEFT = std::find_if(it, m_vWindows.rend(), FINDER);
if (IN_LEFT != m_vWindows.rend())
return *IN_LEFT;
const auto IN_RIGHT = std::find_if(m_vWindows.rbegin(), it, FINDER);
return *IN_RIGHT;
template <typename WINDOWPTR>
static bool isFloatingMatches(WINDOWPTR w, std::optional<bool> floating) {
return !floating.has_value() || w->m_bIsFloating == floating.value();
}

inline static bool isWorkspaceMatches(PHLWINDOW pWindow, const PHLWINDOW w, bool anyWorkspace) {
return anyWorkspace ? w->m_pWorkspace && w->m_pWorkspace->isVisible() : w->m_pWorkspace == pWindow->m_pWorkspace;
template <typename WINDOWPTR>
static bool isWindowAvailableForCycle(WINDOWPTR pWindow, WINDOWPTR w, bool focusableOnly, std::optional<bool> floating, bool anyWorkspace = false) {
return isFloatingMatches(w, floating) &&
(w != pWindow && isWorkspaceMatches(pWindow, w, anyWorkspace) && w->m_bIsMapped && !w->isHidden() && (!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault()));
}

inline static bool isFloatingMatches(PHLWINDOW w, std::optional<bool> floating) {
return !floating.has_value() || w->m_bIsFloating == floating.value();
};
template <typename Iterator>
static PHLWINDOW getWindowPred(Iterator cur, Iterator end, Iterator begin, const std::function<bool(const PHLWINDOW&)> PRED) {
const auto IN_ONE_SIDE = std::find_if(cur, end, PRED);
if (IN_ONE_SIDE != end)
return *IN_ONE_SIDE;
const auto IN_OTHER_SIDE = std::find_if(begin, cur, PRED);
return *IN_OTHER_SIDE;
}

template <typename Iterator>
static PHLWINDOWREF getWeakWindowPred(Iterator cur, Iterator end, Iterator begin, const std::function<bool(const PHLWINDOWREF&)> PRED) {
const auto IN_ONE_SIDE = std::find_if(cur, end, PRED);
if (IN_ONE_SIDE != end)
return *IN_ONE_SIDE;
const auto IN_OTHER_SIDE = std::find_if(begin, cur, PRED);
return *IN_OTHER_SIDE;
}

bool CCompositor::isWindowAvailableForCycle(PHLWINDOW pWindow, const PHLWINDOW w, bool focusableOnly, std::optional<bool> floating, bool anyWorkspace) {
return isFloatingMatches(w, floating) && w != pWindow && isWorkspaceMatches(pWindow, w, anyWorkspace) && w->m_bIsMapped && !w->isHidden() &&
(!focusableOnly || !w->m_sWindowData.noFocus.valueOrDefault());
PHLWINDOWREF CCompositor::getWindowCycleHist(PHLWINDOWREF cur, bool focusableOnly, std::optional<bool> floating, bool visible, bool prev) {
const auto FINDER = [&](const PHLWINDOWREF& w) { return isWindowAvailableForCycle(cur, w, focusableOnly, floating, visible); };
return prev ?
getWeakWindowPred(std::ranges::find(std::ranges::reverse_view(m_vWindowFocusHistory), cur), m_vWindowFocusHistory.rend(), m_vWindowFocusHistory.rbegin(), FINDER) :
getWeakWindowPred(std::ranges::find(m_vWindowFocusHistory, cur), m_vWindowFocusHistory.end(), m_vWindowFocusHistory.begin(), FINDER);
}

PHLWINDOW CCompositor::getWindowCycle(PHLWINDOW cur, bool focusableOnly, std::optional<bool> floating, bool visible, bool prev) {
const auto FINDER = [&](const PHLWINDOW& w) { return isWindowAvailableForCycle(cur, w, focusableOnly, floating, visible); };
return prev ? getWindowPred(std::ranges::find(std::ranges::reverse_view(m_vWindows), cur), m_vWindows.rend(), m_vWindows.rbegin(), FINDER) :
getWindowPred(std::ranges::find(m_vWindows, cur), m_vWindows.end(), m_vWindows.begin(), FINDER);
}

WORKSPACEID CCompositor::getNextAvailableNamedWorkspace() {
Expand Down Expand Up @@ -2757,6 +2769,7 @@ void CCompositor::arrangeMonitors() {

std::vector<PHLMONITOR> toArrange(m_vMonitors.begin(), m_vMonitors.end());
std::vector<PHLMONITOR> arranged;

arranged.reserve(toArrange.size());

Debug::log(LOG, "arrangeMonitors: {} to arrange", toArrange.size());
Expand Down
12 changes: 5 additions & 7 deletions src/Compositor.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#pragma once

#include <functional>
#include <memory>
#include <list>
#include <optional>
#include <sys/resource.h>

#include "defines.hpp"
Expand Down Expand Up @@ -106,8 +108,8 @@ class CCompositor {
void cleanupFadingOut(const MONITORID& monid);
PHLWINDOW getWindowInDirection(PHLWINDOW, char);
PHLWINDOW getWindowInDirection(const CBox& box, PHLWORKSPACE pWorkspace, char dir, PHLWINDOW ignoreWindow = nullptr, bool useVectorAngles = false);
PHLWINDOW getNextWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {}, bool visible = false);
PHLWINDOW getPrevWindowOnWorkspace(PHLWINDOW, bool focusableOnly = false, std::optional<bool> floating = {}, bool visible = false);
PHLWINDOW getWindowCycle(PHLWINDOW cur, bool focusableOnly = false, std::optional<bool> floating = std::nullopt, bool visible = false, bool prev = false);
PHLWINDOWREF getWindowCycleHist(PHLWINDOWREF cur, bool focusableOnly = false, std::optional<bool> floating = std::nullopt, bool visible = false, bool prev = false);
WORKSPACEID getNextAvailableNamedWorkspace();
bool isPointOnAnyMonitor(const Vector2D&);
bool isPointOnReservedArea(const Vector2D& point, const PHLMONITOR monitor = nullptr);
Expand Down Expand Up @@ -150,10 +152,8 @@ class CCompositor {
void setPreferredTransformForSurface(SP<CWLSurfaceResource> pSurface, wl_output_transform transform);
void updateSuspendedStates();
void onNewMonitor(SP<Aquamarine::IOutput> output);

SImageDescription getPreferredImageDescription();
bool shouldChangePreferredImageDescription();

std::string explicitConfigPath;

private:
Expand All @@ -163,11 +163,9 @@ class CCompositor {
void setRandomSplash();
void initManagers(eManagersInitStage stage);
void prepareFallbackOutput();
bool isWindowAvailableForCycle(PHLWINDOW pWindow, PHLWINDOW w, bool focusableOnly, std::optional<bool> floating, bool anyWorkspace = false);

uint64_t m_iHyprlandPID = 0;
wl_event_source* m_critSigSource = nullptr;
rlimit m_sOriginalNofile = {0};
rlimit m_sOriginalNofile = {.rlim_cur = 0};
};

inline std::unique_ptr<CCompositor> g_pCompositor;
22 changes: 10 additions & 12 deletions src/managers/KeybindManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "PointerManager.hpp"
#include "Compositor.hpp"
#include "TokenManager.hpp"
#include "desktop/DesktopTypes.hpp"
#include "eventLoop/EventLoopManager.hpp"
#include "debug/Log.hpp"
#include "helpers/varlist/VarList.hpp"
Expand All @@ -20,6 +21,7 @@
#include "../render/Renderer.hpp"
#include "../hyprerror/HyprError.hpp"

#include <algorithm>
#include <optional>
#include <iterator>
#include <string>
Expand Down Expand Up @@ -1473,7 +1475,7 @@ SDispatchResult CKeybindManager::moveFocusTo(std::string args) {
}

const auto PWINDOWTOCHANGETO = *PFULLCYCLE && PLASTWINDOW->isFullscreen() ?
(arg == 'd' || arg == 'b' || arg == 'r' ? g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true) : g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW, true)) :
g_pCompositor->getWindowCycle(PLASTWINDOW, true, {}, false, arg != 'd' && arg != 'b' && arg != 'r') :
g_pCompositor->getWindowInDirection(PLASTWINDOW, arg);

// Prioritize focus change within groups if the window is a part of it.
Expand Down Expand Up @@ -2221,9 +2223,10 @@ SDispatchResult CKeybindManager::circleNext(std::string arg) {
floatStatus = true;

const auto VISIBLE = args.contains("visible") || args.contains("v");
const auto& w = (args.contains("prev") || args.contains("p") || args.contains("last") || args.contains("l")) ?
g_pCompositor->getPrevWindowOnWorkspace(g_pCompositor->m_pLastWindow.lock(), true, floatStatus, VISIBLE) :
g_pCompositor->getNextWindowOnWorkspace(g_pCompositor->m_pLastWindow.lock(), true, floatStatus, VISIBLE);
const auto PREV = args.contains("prev") || args.contains("p") || args.contains("last") || args.contains("l");
const auto HIST = args.contains("hist") || args.contains("h");
const auto& w = HIST ? g_pCompositor->getWindowCycleHist(g_pCompositor->m_pLastWindow, true, floatStatus, VISIBLE, PREV).lock() :
g_pCompositor->getWindowCycle(g_pCompositor->m_pLastWindow.lock(), true, floatStatus, VISIBLE, PREV);

switchToWindow(w);

Expand Down Expand Up @@ -2620,17 +2623,12 @@ SDispatchResult CKeybindManager::swapnext(std::string arg) {
g_pCompositor->m_pLastWindow->m_pLastCycledWindow.lock() :
nullptr;

if (arg == "last" || arg == "l" || arg == "prev" || arg == "p")
toSwap = g_pCompositor->getPrevWindowOnWorkspace(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW, true);
else
toSwap = g_pCompositor->getNextWindowOnWorkspace(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW, true);
const bool NEED_PREV = arg == "last" || arg == "l" || arg == "prev" || arg == "p";
toSwap = g_pCompositor->getWindowCycle(PLASTCYCLED ? PLASTCYCLED : PLASTWINDOW, true, std::nullopt, false, NEED_PREV);

// sometimes we may come back to ourselves.
if (toSwap == PLASTWINDOW) {
if (arg == "last" || arg == "l" || arg == "prev" || arg == "p")
toSwap = g_pCompositor->getPrevWindowOnWorkspace(PLASTWINDOW, true);
else
toSwap = g_pCompositor->getNextWindowOnWorkspace(PLASTWINDOW, true);
toSwap = g_pCompositor->getWindowCycle(PLASTWINDOW, true, std::nullopt, false, NEED_PREV);
}

g_pLayoutManager->getCurrentLayout()->switchWindows(PLASTWINDOW, toSwap);
Expand Down

0 comments on commit 46cad0e

Please sign in to comment.