Skip to content
This repository has been archived by the owner on Jun 16, 2024. It is now read-only.

[C++ Port] focusWindowByDirection (WIP) #387

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/fsfe/reuse-tool
rev: v0.14.0
hooks:
- id: reuse
Comment on lines -7 to -10
Copy link
Author

@krshrimali krshrimali Jun 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was having this error locally: Unfortunately, your project is not compliant with version 3.0 of the REUSE Specification :-(. So I removed it just for now, later when this PR is in the review stage, maybe we can come back to it and help get this back :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error means, that some of your files do not contain the license headers like:

// SPDX-FileCopyrightText: 2022 Mikhail Zolotukhin <[email protected]>
// SPDX-License-Identifier: MIT

In general, the reuse tool should show you which exact files should contain similar headers.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thank you @gikari! :)

- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.5.1
hooks:
Expand Down
4 changes: 4 additions & 0 deletions src/core/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,19 @@ void Controller::registerShortcuts()

addShortcut("focus_upper_window", "Focus Upper Window", "Meta+K", [=]() {
qDebug(Bi) << "Focus Upper Window Triggered!";
m_engine.focusWindowByDirection(Engine::FocusDirection::Up);
});
addShortcut("focus_bottom_window", "Focus Bottom Window", "Meta+J", [=]() {
qDebug(Bi) << "Focus Bottom Window Triggered!";
m_engine.focusWindowByDirection(Engine::FocusDirection::Down);
});
addShortcut("focus_left_window", "Focus Left Window", "Meta+H", [=]() {
qDebug(Bi) << "Focus Left Window Triggered!";
m_engine.focusWindowByDirection(Engine::FocusDirection::Left);
});
addShortcut("focus_right_window", "Focus Right Window", "Meta+L", [=]() {
qDebug(Bi) << "Focus Right Window Triggered!";
m_engine.focusWindowByDirection(Engine::FocusDirection::Right);
});

addShortcut("move_window_to_next_pos", "Move Window to the Next Position", "", [=]() {
Expand Down
149 changes: 87 additions & 62 deletions src/core/engine/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Engine::Engine(PlasmaApi::Api &api, const Bismuth::Config &config)
, m_windows(api.workspace())
, m_activeLayouts(config)
, m_plasmaApi(api)
, timestamp(0)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a TODO. I think this will require onWindowFocused and hence the signal from QAbstractState - activeChanged.

{
}

Expand Down Expand Up @@ -154,68 +155,92 @@ 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 {};
std::vector<Window> Engine::getNeighborCandidates(const FocusDirection &direction, const Window &basisWindow)
{
// Confirm/Test if it's the right implementation
auto overlap = [](int first_range, int first_maxRange, int second_range, int second_maxRange) {
return (second_range > first_range && second_range < first_maxRange);
};

auto visibleWindowsOnActiveSurface = m_windows.visibleTiledWindowsOn(activeSurface());

int sign = (direction == FocusDirection::Down || direction == FocusDirection::Right) ? 1 : -1;

std::vector<Window> result;

int basis_x = basisWindow.geometry().topLeft().x();
int basis_y = basisWindow.geometry().topLeft().y();
int basis_maxX = basisWindow.geometry().right();
int basis_maxY = basisWindow.geometry().bottom();

if (direction == FocusDirection::Up || direction == FocusDirection::Down) {
std::copy_if(visibleWindowsOnActiveSurface.cbegin(), visibleWindowsOnActiveSurface.cend(), result.begin(), [&](const Window &window) {
int window_x = window.geometry().topLeft().x();
int window_maxX = window.geometry().right();
return window.geometry().y() * sign > basis_y * sign && overlap(basis_x, basis_maxX, window_x, window_maxX);
});
} else {
std::copy_if(visibleWindowsOnActiveSurface.cbegin(), visibleWindowsOnActiveSurface.cend(), result.begin(), [&](const Window &window) {
int window_y = window.geometry().topLeft().y();
int window_maxY = window.geometry().bottom();
return window.geometry().x() * sign > basisWindow.geometry().x() * sign && overlap(basis_y, basis_maxY, window_y, window_maxY);
});
}

return result;
}

int Engine::getClosestRelativeWindowCorner(const Engine::FocusDirection &direction, const std::vector<Window> &neighbors)
{
return std::reduce(neighbors.cbegin(),
neighbors.cend(),
/* initial value */ direction == Engine::FocusDirection::Up || direction == Engine::FocusDirection::Left ? 0 : INT_MAX,
[&](int prevValue, const Window &window) {
switch (direction) {
case Engine::FocusDirection::Up:
return std::max(window.geometry().bottom(), prevValue);
case Engine::FocusDirection::Down:
return std::min(window.geometry().y(), prevValue);
case Engine::FocusDirection::Left:
return std::max(window.geometry().right(), prevValue);
case Engine::FocusDirection::Right:
return std::min(window.geometry().x(), prevValue);
}
});
}

std::vector<Window> getClosestRelativeWindow(const Engine::FocusDirection &direction, const std::vector<Window> &windowArray, const int &closestPoint)
{
std::vector<Window> result;
std::copy_if(windowArray.cbegin(), windowArray.cend(), result.begin(), [&](const Window &window) {
switch (direction) {
case Engine::FocusDirection::Up:
return window.geometry().bottom() > closestPoint - 5;
case Engine::FocusDirection::Down:
return window.geometry().y() < closestPoint + 5;
case Engine::FocusDirection::Left:
return window.geometry().right() > closestPoint - 5;
case Engine::FocusDirection::Right:
return window.geometry().x() < closestPoint + 5;
}
});
return result;
}

/* This function returns the closest window (if any) from the current window for the given direction */
std::optional<Window> Engine::windowNeighbor(Engine::FocusDirection direction, const Window &basisWindow)
{
auto neighborCandidates = getNeighborCandidates(direction, basisWindow);
if (neighborCandidates.empty()) {
return {};
}

int closestRelativeWindowCorner = getClosestRelativeWindowCorner(direction, neighborCandidates);

auto closestWindows = getClosestRelativeWindow(direction, neighborCandidates, closestRelativeWindowCorner);

// TODO: Implement timestamp
return closestWindows.front();
}

Surface Engine::activeSurface() const
Expand Down
7 changes: 7 additions & 0 deletions src/core/engine/engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ struct Engine {
enum class FocusOrder { Next, Previous };
enum class FocusDirection { Up, Down, Right, Left };

int timestamp;
Engine(PlasmaApi::Api &, const Bismuth::Config &);

void addWindow(PlasmaApi::Client);
Expand All @@ -32,8 +33,14 @@ struct Engine {

void arrangeWindowsOnSurfaces(const std::vector<Surface> &);

void onWindowFocused();

private:
std::vector<Window> getNeighborCandidates(const FocusDirection &, const Window &);
int getClosestRelativeWindowCorner(const FocusDirection &, const std::vector<Window> &);
std::vector<Window> getClosestRelativeWindow(const FocusDirection &, const std::vector<Window> &, const int &);
std::optional<Window> windowNeighbor(FocusDirection, const Window &);

Surface activeSurface() const;

void arrangeWindowsOnSurface(const Surface &);
Expand Down
2 changes: 2 additions & 0 deletions src/core/engine/window.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ struct Window {
Tiled,
};

int timestamp = 0;

Window(PlasmaApi::Client, PlasmaApi::Workspace &);

bool operator==(const Window &) const;
Expand Down
11 changes: 11 additions & 0 deletions src/core/engine/windows_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,15 @@ std::vector<Window> WindowsList::visibleWindowsOn(const Surface &surface) const
return result;
}

std::vector<Window> WindowsList::visibleTiledWindowsOn(const Surface &surface) const
{
auto result = std::vector<Window>();
for (auto [_, window] : m_windowMap) {
if (window.visibleOn(surface) && window.mode() == Window::Mode::Tiled) {
result.push_back(window);
}
}
return result;
}

}
1 change: 1 addition & 0 deletions src/core/engine/windows_list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ struct WindowsList {
std::optional<Window> activeWindow() const;

std::vector<Window> visibleWindowsOn(const Surface &surface) const;
std::vector<Window> visibleTiledWindowsOn(const Surface &surface) const;

private:
std::map<PlasmaApi::Client, Window> m_windowMap{};
Expand Down
6 changes: 3 additions & 3 deletions src/kwinscript/controller/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export interface Controller {

/**
* React to window being moved.
* @param window the window, which it being moved.
* @param window the window, which is being moved.
*/
onWindowMove(window: EngineWindow): void;

Expand Down Expand Up @@ -143,9 +143,9 @@ export interface Controller {

/**
* Ask engine to manage the window
* @param win the window which needs to be managed.
* @param window the window which needs to be managed.
*/
manageWindow(win: EngineWindow): void;
manageWindow(window: EngineWindow): void;

/**
* The function is called when the script is destroyed.
Expand Down