chore(new_backend): split focus by direction and order

This commit is contained in:
Mikhail Zolotukhin 2022-04-01 21:48:37 +03:00 committed by Genda
parent ebf54b14cb
commit 314410ba23
3 changed files with 107 additions and 24 deletions

View File

@ -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", [=]() {

View File

@ -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();

View File

@ -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 &);