mirror of
https://github.com/Bismuth-Forge/bismuth.git
synced 2024-10-05 12:37:47 +03:00
chore(new_backend): split focus by direction and order
This commit is contained in:
parent
ebf54b14cb
commit
314410ba23
@ -79,11 +79,11 @@ void Controller::registerShortcuts()
|
||||
|
||||
addShortcut("focus_next_window", "Focus Next Window", "", [=]() {
|
||||
qDebug(Bi) << "Focus Next Window Triggered!";
|
||||
m_engine.focusWindow(Engine::RelDirection::Next);
|
||||
m_engine.focusWindowByOrder(Engine::FocusOrder::Next);
|
||||
});
|
||||
addShortcut("focus_prev_window", "Focus Previous Window", "", [=]() {
|
||||
qDebug(Bi) << "Focus Previous Window Triggered!";
|
||||
m_engine.focusWindow(Engine::RelDirection::Previous);
|
||||
m_engine.focusWindowByOrder(Engine::FocusOrder::Previous);
|
||||
});
|
||||
|
||||
addShortcut("focus_upper_window", "Focus Upper Window", "Meta+K", [=]() {
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "config.hpp"
|
||||
#include "engine/surface.hpp"
|
||||
#include "engine/window.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "plasma-api/api.hpp"
|
||||
|
||||
@ -51,47 +52,62 @@ void Engine::removeWindow(PlasmaApi::Client client)
|
||||
m_windows.remove(client);
|
||||
}
|
||||
|
||||
void Engine::focusWindow(RelDirection direction)
|
||||
void Engine::focusWindowByOrder(FocusOrder focusOrder)
|
||||
{
|
||||
auto activeWindow = m_windows.activeWindow();
|
||||
|
||||
auto currentSurface = activeSurface();
|
||||
|
||||
auto windowsToChoseFrom = m_windows.visibleWindowsOn(currentSurface);
|
||||
auto windowsToChoseFrom = m_windows.visibleWindowsOn(activeSurface());
|
||||
|
||||
if (windowsToChoseFrom.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If there is no current window, select the first one.
|
||||
auto activeWindow = m_windows.activeWindow();
|
||||
if (!activeWindow.has_value()) {
|
||||
activeWindow = windowsToChoseFrom.front();
|
||||
}
|
||||
|
||||
auto it = std::find(windowsToChoseFrom.begin(), windowsToChoseFrom.end(), activeWindow.value());
|
||||
auto windowIter = std::find(windowsToChoseFrom.begin(), windowsToChoseFrom.end(), activeWindow.value());
|
||||
|
||||
// If there is no windows to chose - do nothing
|
||||
if (it == windowsToChoseFrom.end()) {
|
||||
if (windowIter == windowsToChoseFrom.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Direction focus split
|
||||
if (direction == RelDirection::Next) {
|
||||
it++;
|
||||
if (it == windowsToChoseFrom.end()) {
|
||||
it = windowsToChoseFrom.begin();
|
||||
// Select the next or the previous window circularly
|
||||
if (focusOrder == FocusOrder::Next) {
|
||||
windowIter++;
|
||||
if (windowIter == windowsToChoseFrom.end()) {
|
||||
windowIter = windowsToChoseFrom.begin();
|
||||
}
|
||||
} else if (direction == RelDirection::Previous) {
|
||||
it--;
|
||||
if (it < windowsToChoseFrom.begin()) {
|
||||
it = --windowsToChoseFrom.end();
|
||||
} else if (focusOrder == FocusOrder::Previous) {
|
||||
windowIter--;
|
||||
if (windowIter < windowsToChoseFrom.begin()) {
|
||||
windowIter = --windowsToChoseFrom.end();
|
||||
}
|
||||
}
|
||||
windowIter->activate();
|
||||
qDebug() << "Activated window title:" << windowIter->caption();
|
||||
}
|
||||
|
||||
auto windowToActivate = *it;
|
||||
void Engine::focusWindowByDirection(FocusDirection direction)
|
||||
{
|
||||
auto windowsToChoseFrom = m_windows.visibleWindowsOn(activeSurface());
|
||||
|
||||
windowToActivate.activate();
|
||||
qDebug() << "Activated window title:" << windowToActivate.caption();
|
||||
if (windowsToChoseFrom.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If there is no current window, select the first one.
|
||||
auto activeWindow = m_windows.activeWindow();
|
||||
if (!activeWindow.has_value()) {
|
||||
activeWindow = windowsToChoseFrom.front();
|
||||
}
|
||||
|
||||
auto window = windowNeighbor(direction, activeWindow.value());
|
||||
|
||||
if (window.has_value()) {
|
||||
window->activate();
|
||||
}
|
||||
}
|
||||
|
||||
void Engine::arrangeWindowsOnAllSurfaces()
|
||||
@ -138,6 +154,70 @@ void Engine::arrangeWindowsOnSurfaces(const std::vector<Surface> &surfaces)
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<Window> Engine::windowNeighbor(FocusDirection direction, const Window &basisWindow)
|
||||
{
|
||||
/**
|
||||
* Tests if two ranges are overlapping
|
||||
* @param min1 Range 1, begin
|
||||
* @param max1 Range 1, end
|
||||
* @param min2 Range 2, begin
|
||||
* @param max2 Range 2, end
|
||||
*/
|
||||
// auto overlap = [](int min1, int max1, int min2, int max2) {
|
||||
// return std::max(0, std::min(max1, max2) - std::max(min1, min2)) > 0;
|
||||
// };
|
||||
//
|
||||
// auto getNeighborCandidates = [&](const Window &basis, FocusDirection direction) {
|
||||
// auto surfaceWindows = m_windows.visibleWindowsOn(activeSurface());
|
||||
//
|
||||
// // Flipping all inputs' signs allows for the same logic to find closest windows in either direction
|
||||
// auto sign = direction == FocusDirection::Down || direction == FocusDirection::Right ? 1 : -1;
|
||||
//
|
||||
// auto result = std::vector<Window>();
|
||||
// if (direction == FocusDirection::Up || direction == FocusDirection::Down) {
|
||||
// std::copy_if(surfaceWindows.cbegin(), surfaceWindows.cend(), result.begin(), [&](const Window &window) {
|
||||
// return window.geometry().y() * sign > basis.geometry().y() * sign
|
||||
// && overlap(basis.geometry().x(), basis.geometry().right(), window.geometry().x(), window.geometry().right());
|
||||
// });
|
||||
// } else {
|
||||
// std::copy_if(surfaceWindows.cbegin(), surfaceWindows.cend(), result.begin(), [&](const Window window) {
|
||||
// return window.geometry().x() * sign > basis.geometry().x() * sign
|
||||
// && overlap(basis.geometry().y(), basis.geometry().bottom(), window.geometry().y(), window.geometry().bottom());
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// return result;
|
||||
// };
|
||||
//
|
||||
// auto neighborCandidates = getNeighborCandidates(basisWindow, direction);
|
||||
//
|
||||
// if (neighborCandidates.empty()) {
|
||||
// return {};
|
||||
// }
|
||||
//
|
||||
// auto getClosestRelativWindowCorner = [&]() {
|
||||
// return std::reduce(neighborCandidates.cbegin(), neighborCandidates.cend(), [&](int prevValue, const Window &window) {
|
||||
// if (direction == FocusDirection::Up) {
|
||||
// return std::max(window.geometry().bottom(), prevValue);
|
||||
// } else if (direction == FocusDirection::Down) {
|
||||
// return std::min(window.geometry().y(), prevValue);
|
||||
// } else if (direction == FocusDirection::Left) {
|
||||
// return std::max(window.geometry().right(), prevValue);
|
||||
// } else {
|
||||
// return std::min(window.geometry().x(), prevValue);
|
||||
// }
|
||||
// });
|
||||
// };
|
||||
// auto closestWindowCorner = getClosestRelativWindowCorner(neighborCandidates, dir);
|
||||
|
||||
// auto closestWindows = this.getClosestRelativeWindow(neighborCandidates, dir, closestWindowCorner);
|
||||
|
||||
// return closestWindows.front();
|
||||
|
||||
// TODO Implement
|
||||
return {};
|
||||
}
|
||||
|
||||
Surface Engine::activeSurface() const
|
||||
{
|
||||
auto activeScreen = m_plasmaApi.workspace().activeScreen();
|
||||
|
@ -12,14 +12,16 @@
|
||||
namespace Bismuth
|
||||
{
|
||||
struct Engine {
|
||||
enum class RelDirection { Next, Previous, Up, Down, Right, Left };
|
||||
enum class FocusOrder { Next, Previous };
|
||||
enum class FocusDirection { Up, Down, Right, Left };
|
||||
|
||||
Engine(PlasmaApi::Api &, const Bismuth::Config &);
|
||||
|
||||
void addWindow(PlasmaApi::Client);
|
||||
void removeWindow(PlasmaApi::Client);
|
||||
|
||||
void focusWindow(RelDirection);
|
||||
void focusWindowByOrder(FocusOrder);
|
||||
void focusWindowByDirection(FocusDirection);
|
||||
|
||||
void arrangeWindowsOnAllSurfaces();
|
||||
|
||||
@ -31,6 +33,7 @@ struct Engine {
|
||||
void arrangeWindowsOnSurfaces(const std::vector<Surface> &);
|
||||
|
||||
private:
|
||||
std::optional<Window> windowNeighbor(FocusDirection, const Window &);
|
||||
Surface activeSurface() const;
|
||||
|
||||
void arrangeWindowsOnSurface(const Surface &);
|
||||
|
Loading…
Reference in New Issue
Block a user