mirror of
https://github.com/hyprwm/Hypr.git
synced 2024-11-25 06:25:57 +01:00
many fixes for multi monitor, added also the new window tree system 🎉
🎉
This commit is contained in:
parent
c6cd584410
commit
4ffa3ab6a1
7 changed files with 191 additions and 92 deletions
|
@ -5,6 +5,7 @@ project(Hypr
|
||||||
)
|
)
|
||||||
|
|
||||||
add_compile_options(-std=c++17)
|
add_compile_options(-std=c++17)
|
||||||
|
add_compile_options(-Wall -Wextra)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
file(GLOB_RECURSE SRCFILES "src/*.cpp")
|
file(GLOB_RECURSE SRCFILES "src/*.cpp")
|
||||||
|
|
|
@ -20,7 +20,7 @@ Hypr is a Linux tiling window manager for Xorg. It's written in XCB with modern
|
||||||
- [x] Workspaces
|
- [x] Workspaces
|
||||||
- [x] Moving windows / user input (e.g. fullscreening) ~ More to be done probably
|
- [x] Moving windows / user input (e.g. fullscreening) ~ More to be done probably
|
||||||
- [ ] True lerp animations
|
- [ ] True lerp animations
|
||||||
- [ ] Rewriting the window system to be a tree
|
- [x] Rewriting the window system to be a tree
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,50 @@ void Events::eventMapWindow(xcb_generic_event_t* event) {
|
||||||
window.setDefaultPosition(Vector2D(0,0));
|
window.setDefaultPosition(Vector2D(0,0));
|
||||||
window.setDefaultSize(Vector2D(g_pWindowManager->Screen->width_in_pixels/2.f,g_pWindowManager->Screen->height_in_pixels/2.f));
|
window.setDefaultSize(Vector2D(g_pWindowManager->Screen->width_in_pixels/2.f,g_pWindowManager->Screen->height_in_pixels/2.f));
|
||||||
|
|
||||||
|
// Set the parent
|
||||||
|
// check if lastwindow is on our workspace
|
||||||
|
if (auto PLASTWINDOW = g_pWindowManager->getWindowFromDrawable(g_pWindowManager->LastWindow); PLASTWINDOW
|
||||||
|
&& PLASTWINDOW->getWorkspaceID() == g_pWindowManager->activeWorkspaces[CURRENTSCREEN]) {
|
||||||
|
// LastWindow is on our workspace, let's make a new split node
|
||||||
|
|
||||||
|
if (PLASTWINDOW->getIsFloating()) {
|
||||||
|
// find a window manually
|
||||||
|
PLASTWINDOW = g_pWindowManager->findWindowAtCursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
CWindow newWindowSplitNode;
|
||||||
|
newWindowSplitNode.setPosition(PLASTWINDOW->getPosition());
|
||||||
|
newWindowSplitNode.setSize(PLASTWINDOW->getSize());
|
||||||
|
|
||||||
|
newWindowSplitNode.setChildNodeAID(PLASTWINDOW->getDrawable());
|
||||||
|
newWindowSplitNode.setChildNodeBID(E->window);
|
||||||
|
|
||||||
|
newWindowSplitNode.setParentNodeID(PLASTWINDOW->getParentNodeID());
|
||||||
|
|
||||||
|
newWindowSplitNode.setWorkspaceID(window.getWorkspaceID());
|
||||||
|
newWindowSplitNode.setMonitor(window.getMonitor());
|
||||||
|
|
||||||
|
// generates a negative node ID
|
||||||
|
newWindowSplitNode.generateNodeID();
|
||||||
|
|
||||||
|
// update the parent if exists
|
||||||
|
if (const auto PREVPARENT = g_pWindowManager->getWindowFromDrawable(PLASTWINDOW->getParentNodeID()); PREVPARENT) {
|
||||||
|
if (PREVPARENT->getChildNodeAID() == PLASTWINDOW->getDrawable()) {
|
||||||
|
PREVPARENT->setChildNodeAID(newWindowSplitNode.getDrawable());
|
||||||
|
} else {
|
||||||
|
PREVPARENT->setChildNodeBID(newWindowSplitNode.getDrawable());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.setParentNodeID(newWindowSplitNode.getDrawable());
|
||||||
|
PLASTWINDOW->setParentNodeID(newWindowSplitNode.getDrawable());
|
||||||
|
|
||||||
|
g_pWindowManager->addWindowToVectorSafe(newWindowSplitNode);
|
||||||
|
} else {
|
||||||
|
// LastWindow is not on our workspace, so set the parent to 0.
|
||||||
|
window.setParentNodeID(0);
|
||||||
|
}
|
||||||
|
|
||||||
// Also sets the old one
|
// Also sets the old one
|
||||||
g_pWindowManager->calculateNewWindowParams(&window);
|
g_pWindowManager->calculateNewWindowParams(&window);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,48 @@
|
||||||
#include "window.hpp"
|
#include "window.hpp"
|
||||||
|
#include "windowManager.hpp"
|
||||||
|
|
||||||
CWindow::CWindow() { this->setDirty(true); this->setFullscreen(false); this->setIsFloating(false); }
|
CWindow::CWindow() { this->setDirty(true); this->setFullscreen(false); this->setIsFloating(false); this->setParentNodeID(0); this->setChildNodeAID(0); this->setChildNodeBID(0); }
|
||||||
CWindow::~CWindow() { }
|
CWindow::~CWindow() { }
|
||||||
|
|
||||||
|
void CWindow::generateNodeID() {
|
||||||
|
|
||||||
|
int64_t lowest = -1;
|
||||||
|
for (auto& window : g_pWindowManager->windows) {
|
||||||
|
if ((int64_t)window.getDrawable() < lowest) {
|
||||||
|
lowest = (int64_t)window.getDrawable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_iDrawable = lowest - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindow::setDirtyRecursive(bool val) {
|
||||||
|
m_bDirty = val;
|
||||||
|
|
||||||
|
if (m_iChildNodeAID != 0) {
|
||||||
|
g_pWindowManager->getWindowFromDrawable(m_iChildNodeAID)->setDirtyRecursive(val);
|
||||||
|
g_pWindowManager->getWindowFromDrawable(m_iChildNodeBID)->setDirtyRecursive(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindow::recalcSizePosRecursive() {
|
||||||
|
if (m_iChildNodeAID != 0) {
|
||||||
|
const auto HORIZONTAL = m_vecSize.x > m_vecSize.y;
|
||||||
|
g_pWindowManager->getWindowFromDrawable(m_iChildNodeAID)->setPosition(m_vecPosition);
|
||||||
|
g_pWindowManager->getWindowFromDrawable(m_iChildNodeBID)->setPosition(m_vecPosition + (HORIZONTAL ? Vector2D(m_vecSize.x / 2.f, 0) : Vector2D(0, m_vecSize.y / 2.f)));
|
||||||
|
|
||||||
|
g_pWindowManager->getWindowFromDrawable(m_iChildNodeAID)->setSize(Vector2D(m_vecSize.x / (HORIZONTAL ? 2 : 1), m_vecSize.y / (HORIZONTAL ? 1 : 2)));
|
||||||
|
g_pWindowManager->getWindowFromDrawable(m_iChildNodeBID)->setSize(Vector2D(m_vecSize.x / (HORIZONTAL ? 2 : 1), m_vecSize.y / (HORIZONTAL ? 1 : 2)));
|
||||||
|
|
||||||
|
g_pWindowManager->getWindowFromDrawable(m_iChildNodeAID)->setDirty(true);
|
||||||
|
g_pWindowManager->getWindowFromDrawable(m_iChildNodeBID)->setDirty(true);
|
||||||
|
|
||||||
|
if (m_iChildNodeAID < 0) {
|
||||||
|
g_pWindowManager->getWindowFromDrawable(m_iChildNodeAID)->recalcSizePosRecursive();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_iChildNodeBID < 0) {
|
||||||
|
g_pWindowManager->getWindowFromDrawable(m_iChildNodeBID)->recalcSizePosRecursive();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,17 +14,38 @@ public:
|
||||||
void resize(Vector2D size);
|
void resize(Vector2D size);
|
||||||
void resize(float percx, float percy);
|
void resize(float percx, float percy);
|
||||||
|
|
||||||
|
// ------------------------------------- //
|
||||||
|
// Node Stuff //
|
||||||
|
// ------------------------------------- //
|
||||||
|
|
||||||
|
// IDs:
|
||||||
|
// > 0 : Windows
|
||||||
|
// == 0 : None
|
||||||
|
// < 0 : Nodes
|
||||||
|
|
||||||
|
EXPOSED_MEMBER(ParentNodeID, int64_t, i);
|
||||||
|
|
||||||
|
EXPOSED_MEMBER(ChildNodeAID, int64_t, i);
|
||||||
|
EXPOSED_MEMBER(ChildNodeBID, int64_t, i);
|
||||||
|
|
||||||
|
void generateNodeID();
|
||||||
|
|
||||||
|
// ------------------------------------- //
|
||||||
|
|
||||||
std::string getName();
|
std::string getName();
|
||||||
|
|
||||||
// Tells the window manager to reload the window's params
|
// Tells the window manager to reload the window's params
|
||||||
EXPOSED_MEMBER(Dirty, bool, b);
|
EXPOSED_MEMBER(Dirty, bool, b);
|
||||||
|
|
||||||
|
void setDirtyRecursive(bool);
|
||||||
|
void recalcSizePosRecursive();
|
||||||
|
|
||||||
EXPOSED_MEMBER(Size, Vector2D, vec);
|
EXPOSED_MEMBER(Size, Vector2D, vec);
|
||||||
EXPOSED_MEMBER(EffectiveSize, Vector2D, vec);
|
EXPOSED_MEMBER(EffectiveSize, Vector2D, vec);
|
||||||
EXPOSED_MEMBER(EffectivePosition, Vector2D, vec);
|
EXPOSED_MEMBER(EffectivePosition, Vector2D, vec);
|
||||||
EXPOSED_MEMBER(Position, Vector2D, vec);
|
EXPOSED_MEMBER(Position, Vector2D, vec);
|
||||||
EXPOSED_MEMBER(IsFloating, bool, b);
|
EXPOSED_MEMBER(IsFloating, bool, b);
|
||||||
EXPOSED_MEMBER(Drawable, xcb_drawable_t, i);
|
EXPOSED_MEMBER(Drawable, int64_t, i); // int64_t because it's my internal ID system too.
|
||||||
|
|
||||||
// Fullscreen
|
// Fullscreen
|
||||||
EXPOSED_MEMBER(Fullscreen, bool, b);
|
EXPOSED_MEMBER(Fullscreen, bool, b);
|
||||||
|
|
|
@ -55,7 +55,7 @@ void CWindowManager::setupRandrMonitors() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(NONE, "Monitor " + monitors[monitors.size() - 1].szName + ": " + std::to_string(monitors[i].vecSize.x) + "x" + std::to_string(monitors[monitors.size() - 1].vecSize.y) +
|
Debug::log(NONE, "Monitor " + monitors[monitors.size() - 1].szName + ": " + std::to_string(monitors[i].vecSize.x) + "x" + std::to_string(monitors[monitors.size() - 1].vecSize.y) +
|
||||||
", at " + std::to_string(monitors[monitors.size() - 1].vecPosition.x) + "," + std::to_string(monitors[monitors.size() - 1].vecSize.y));
|
", at " + std::to_string(monitors[monitors.size() - 1].vecPosition.x) + "," + std::to_string(monitors[monitors.size() - 1].vecPosition.y) + ", ID: " + std::to_string(monitors[monitors.size() - 1].ID));
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto EXTENSIONREPLY = xcb_get_extension_data(DisplayConnection, &xcb_randr_id);
|
const auto EXTENSIONREPLY = xcb_get_extension_data(DisplayConnection, &xcb_randr_id);
|
||||||
|
@ -65,31 +65,29 @@ void CWindowManager::setupRandrMonitors() {
|
||||||
//listen for screen change events
|
//listen for screen change events
|
||||||
xcb_randr_select_input(DisplayConnection, Screen->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
|
xcb_randr_select_input(DisplayConnection, Screen->root, XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort monitors for my convenience thanks
|
|
||||||
std::sort(monitors.begin(), monitors.end(), [](SMonitor& a, SMonitor& b) {
|
|
||||||
return a.vecPosition.x < b.vecPosition.x;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindowManager::setupManager() {
|
void CWindowManager::setupManager() {
|
||||||
setupRandrMonitors();
|
setupRandrMonitors();
|
||||||
|
|
||||||
ConfigManager::init();
|
|
||||||
|
|
||||||
if (monitors.size() == 0) {
|
if (monitors.size() == 0) {
|
||||||
// RandR failed!
|
// RandR failed!
|
||||||
Debug::log(WARN, "RandR failed!");
|
Debug::log(WARN, "RandR failed!");
|
||||||
|
|
||||||
|
#define TESTING_MON_AMOUNT 3
|
||||||
|
for (int i = 0; i < TESTING_MON_AMOUNT /* Testing on 3 monitors, RandR shouldnt fail on a real desktop */; ++i) {
|
||||||
monitors.push_back(SMonitor());
|
monitors.push_back(SMonitor());
|
||||||
monitors[0].vecPosition = Vector2D(0, 0);
|
monitors[i].vecPosition = Vector2D(i * Screen->width_in_pixels / TESTING_MON_AMOUNT, 0);
|
||||||
monitors[0].vecSize = Vector2D(Screen->width_in_pixels, Screen->height_in_pixels);
|
monitors[i].vecSize = Vector2D(Screen->width_in_pixels / TESTING_MON_AMOUNT, Screen->height_in_pixels);
|
||||||
monitors[0].ID = 0;
|
monitors[i].ID = i;
|
||||||
monitors[0].szName = "Screen";
|
monitors[i].szName = "Screen" + std::to_string(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug::log(LOG, "RandR done.");
|
Debug::log(LOG, "RandR done.");
|
||||||
|
|
||||||
|
ConfigManager::init();
|
||||||
|
|
||||||
Values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE;
|
Values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE;
|
||||||
xcb_change_window_attributes_checked(DisplayConnection, Screen->root,
|
xcb_change_window_attributes_checked(DisplayConnection, Screen->root,
|
||||||
XCB_CW_EVENT_MASK, Values);
|
XCB_CW_EVENT_MASK, Values);
|
||||||
|
@ -118,7 +116,7 @@ void CWindowManager::setupManager() {
|
||||||
Debug::log(LOG, "Keys done.");
|
Debug::log(LOG, "Keys done.");
|
||||||
|
|
||||||
// Add workspaces to the monitors
|
// Add workspaces to the monitors
|
||||||
for (int i = 0; i < monitors.size(); ++i) {
|
for (long unsigned int i = 0; i < monitors.size(); ++i) {
|
||||||
CWorkspace protoWorkspace;
|
CWorkspace protoWorkspace;
|
||||||
protoWorkspace.setID(i + 1);
|
protoWorkspace.setID(i + 1);
|
||||||
protoWorkspace.setMonitor(i);
|
protoWorkspace.setMonitor(i);
|
||||||
|
@ -216,35 +214,6 @@ bool CWindowManager::handleEvent() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add an empty space check
|
|
||||||
void CWindowManager::performSanityCheckForWorkspace(int WorkspaceID) {
|
|
||||||
for (auto& windowA : windows) {
|
|
||||||
if (windowA.getWorkspaceID() != WorkspaceID)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (auto& windowB : windows) {
|
|
||||||
if (windowB.getWorkspaceID() != WorkspaceID)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (windowB.getDrawable() == windowA.getDrawable())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Check if A and B overlap, if don't, continue
|
|
||||||
if ((windowA.getPosition().x >= (windowB.getPosition() + windowB.getSize()).x || windowB.getPosition().x >= (windowA.getPosition() + windowA.getSize()).x
|
|
||||||
|| windowA.getPosition().y >= (windowB.getPosition() + windowB.getSize()).y || windowB.getPosition().y >= (windowA.getPosition() + windowA.getSize()).y)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Overlap detected! Fix window B
|
|
||||||
if (windowB.getIsFloating()) {
|
|
||||||
calculateNewTileSetOldTile(&windowB);
|
|
||||||
} else {
|
|
||||||
calculateNewFloatingWindow(&windowB);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CWindowManager::cleanupUnusedWorkspaces() {
|
void CWindowManager::cleanupUnusedWorkspaces() {
|
||||||
std::vector<CWorkspace> temp = workspaces;
|
std::vector<CWorkspace> temp = workspaces;
|
||||||
|
|
||||||
|
@ -279,6 +248,12 @@ void CWindowManager::refreshDirtyWindows() {
|
||||||
for(auto& window : windows) {
|
for(auto& window : windows) {
|
||||||
if (window.getDirty()) {
|
if (window.getDirty()) {
|
||||||
|
|
||||||
|
// Check if the window isn't a node
|
||||||
|
if (window.getChildNodeAID() != 0) {
|
||||||
|
window.setDirty(false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
setEffectiveSizePosUsingConfig(&window);
|
setEffectiveSizePosUsingConfig(&window);
|
||||||
|
|
||||||
// Fullscreen flag
|
// Fullscreen flag
|
||||||
|
@ -367,7 +342,7 @@ void CWindowManager::setFocusedWindow(xcb_drawable_t window) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CWindow* CWindowManager::getWindowFromDrawable(xcb_drawable_t window) {
|
CWindow* CWindowManager::getWindowFromDrawable(int64_t window) {
|
||||||
for(auto& w : windows) {
|
for(auto& w : windows) {
|
||||||
if (w.getDrawable() == window) {
|
if (w.getDrawable() == window) {
|
||||||
return &w;
|
return &w;
|
||||||
|
@ -420,9 +395,9 @@ void CWindowManager::setEffectiveSizePosUsingConfig(CWindow* pWindow) {
|
||||||
//TODO: make windows with no bar taller, this aint working chief
|
//TODO: make windows with no bar taller, this aint working chief
|
||||||
|
|
||||||
// do gaps, set top left
|
// do gaps, set top left
|
||||||
pWindow->setEffectivePosition(pWindow->getEffectivePosition() + Vector2D(DISPLAYLEFT ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in"), DISPLAYTOP ? ConfigManager::getInt("gaps_out") + (MONITOR->ID != statusBar.getMonitorID() ? ConfigManager::getInt("bar_height") : 0) : ConfigManager::getInt("gaps_in")));
|
pWindow->setEffectivePosition(pWindow->getEffectivePosition() + Vector2D(DISPLAYLEFT ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in"), DISPLAYTOP ? ConfigManager::getInt("gaps_out") + (MONITOR->ID == statusBar.getMonitorID() ? ConfigManager::getInt("bar_height") : 0) : ConfigManager::getInt("gaps_in")));
|
||||||
// fix to old size bottom right
|
// fix to old size bottom right
|
||||||
pWindow->setEffectiveSize(pWindow->getEffectiveSize() - Vector2D(DISPLAYLEFT ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in"), DISPLAYTOP ? ConfigManager::getInt("gaps_out") + (MONITOR->ID != statusBar.getMonitorID() ? ConfigManager::getInt("bar_height") : 0) : ConfigManager::getInt("gaps_in")));
|
pWindow->setEffectiveSize(pWindow->getEffectiveSize() - Vector2D(DISPLAYLEFT ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in"), DISPLAYTOP ? ConfigManager::getInt("gaps_out") + (MONITOR->ID == statusBar.getMonitorID() ? ConfigManager::getInt("bar_height") : 0) : ConfigManager::getInt("gaps_in")));
|
||||||
// set bottom right
|
// set bottom right
|
||||||
pWindow->setEffectiveSize(pWindow->getEffectiveSize() - Vector2D(DISPLAYRIGHT ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in"), DISPLAYBOTTOM ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in")));
|
pWindow->setEffectiveSize(pWindow->getEffectiveSize() - Vector2D(DISPLAYRIGHT ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in"), DISPLAYBOTTOM ? ConfigManager::getInt("gaps_out") : ConfigManager::getInt("gaps_in")));
|
||||||
}
|
}
|
||||||
|
@ -459,33 +434,45 @@ CWindow* CWindowManager::findWindowAtCursor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CWindowManager::calculateNewTileSetOldTile(CWindow* pWindow) {
|
void CWindowManager::calculateNewTileSetOldTile(CWindow* pWindow) {
|
||||||
auto PLASTWINDOW = getWindowFromDrawable(LastWindow);
|
|
||||||
|
|
||||||
if (PLASTWINDOW && (PLASTWINDOW->getIsFloating() || PLASTWINDOW->getWorkspaceID() != pWindow->getWorkspaceID())) {
|
// Get the parent and both children, one of which will be pWindow
|
||||||
// find a window manually
|
const auto PPARENT = getWindowFromDrawable(pWindow->getParentNodeID());
|
||||||
PLASTWINDOW = findWindowAtCursor();
|
|
||||||
|
if (!PPARENT) {
|
||||||
|
// New window on this workspace.
|
||||||
|
// Open a fullscreen window.
|
||||||
|
const auto MONITOR = getMonitorFromCursor();
|
||||||
|
pWindow->setSize(Vector2D(MONITOR->vecSize.x, MONITOR->vecSize.y));
|
||||||
|
pWindow->setPosition(Vector2D(MONITOR->vecPosition.x, MONITOR->vecPosition.y));
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PLASTWINDOW) {
|
// Get the sibling
|
||||||
const auto PLASTSIZE = PLASTWINDOW->getSize();
|
const auto PSIBLING = getWindowFromDrawable(PPARENT->getChildNodeAID() == pWindow->getDrawable() ? PPARENT->getChildNodeBID() : PPARENT->getChildNodeAID());
|
||||||
const auto PLASTPOS = PLASTWINDOW->getPosition();
|
|
||||||
|
// Should NEVER be null
|
||||||
|
if (PSIBLING) {
|
||||||
|
const auto PLASTSIZE = PPARENT->getSize();
|
||||||
|
const auto PLASTPOS = PPARENT->getPosition();
|
||||||
|
|
||||||
if (PLASTSIZE.x > PLASTSIZE.y) {
|
if (PLASTSIZE.x > PLASTSIZE.y) {
|
||||||
PLASTWINDOW->setSize(Vector2D(PLASTSIZE.x / 2.f, PLASTSIZE.y));
|
PSIBLING->setPosition(Vector2D(PLASTPOS.x, PLASTPOS.y));
|
||||||
|
PSIBLING->setSize(Vector2D(PLASTSIZE.x / 2.f, PLASTSIZE.y));
|
||||||
pWindow->setSize(Vector2D(PLASTSIZE.x / 2.f, PLASTSIZE.y));
|
pWindow->setSize(Vector2D(PLASTSIZE.x / 2.f, PLASTSIZE.y));
|
||||||
pWindow->setPosition(Vector2D(PLASTPOS.x + PLASTSIZE.x / 2.f, PLASTPOS.y));
|
pWindow->setPosition(Vector2D(PLASTPOS.x + PLASTSIZE.x / 2.f, PLASTPOS.y));
|
||||||
} else {
|
} else {
|
||||||
PLASTWINDOW->setSize(Vector2D(PLASTSIZE.x, PLASTSIZE.y / 2.f));
|
PSIBLING->setPosition(Vector2D(PLASTPOS.x, PLASTPOS.y));
|
||||||
|
PSIBLING->setSize(Vector2D(PLASTSIZE.x, PLASTSIZE.y / 2.f));
|
||||||
pWindow->setSize(Vector2D(PLASTSIZE.x, PLASTSIZE.y / 2.f));
|
pWindow->setSize(Vector2D(PLASTSIZE.x, PLASTSIZE.y / 2.f));
|
||||||
pWindow->setPosition(Vector2D(PLASTPOS.x, PLASTPOS.y + PLASTSIZE.y / 2.f));
|
pWindow->setPosition(Vector2D(PLASTPOS.x, PLASTPOS.y + PLASTSIZE.y / 2.f));
|
||||||
}
|
}
|
||||||
|
|
||||||
PLASTWINDOW->setDirty(true);
|
PSIBLING->setDirty(true);
|
||||||
} else {
|
} else {
|
||||||
// Open a fullscreen window
|
Debug::log(ERR, "Sibling node was null?? pWindow x,y,w,h: " + std::to_string(pWindow->getPosition().x) + " "
|
||||||
const auto MONITOR = getMonitorFromCursor();
|
+ std::to_string(pWindow->getPosition().y) + " " + std::to_string(pWindow->getSize().x) + " "
|
||||||
pWindow->setSize(Vector2D(MONITOR->vecSize.x, MONITOR->vecSize.y));
|
+ std::to_string(pWindow->getSize().y));
|
||||||
pWindow->setPosition(Vector2D(MONITOR->vecPosition.x, MONITOR->vecPosition.y));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -593,32 +580,39 @@ void CWindowManager::fixWindowOnClose(CWindow* pClosedWindow) {
|
||||||
if (!pClosedWindow)
|
if (!pClosedWindow)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto WORKSPACE = activeWorkspaces[getMonitorFromWindow(pClosedWindow)->ID];
|
// Get the parent and both children, one of which will be pWindow
|
||||||
|
const auto PPARENT = getWindowFromDrawable(pClosedWindow->getParentNodeID());
|
||||||
|
|
||||||
// Fix if was fullscreen
|
if (!PPARENT)
|
||||||
if (pClosedWindow->getFullscreen())
|
return; // if there was no parent, we do not need to update anything. it was a fullscreen window, the only one on a given workspace.
|
||||||
g_pWindowManager->getWorkspaceByID(WORKSPACE)->setHasFullscreenWindow(false);
|
|
||||||
|
|
||||||
// get the first neighboring window
|
// Get the sibling
|
||||||
CWindow* neighbor = nullptr;
|
const auto PSIBLING = getWindowFromDrawable(PPARENT->getChildNodeAID() == pClosedWindow->getDrawable() ? PPARENT->getChildNodeBID() : PPARENT->getChildNodeAID());
|
||||||
for(auto& w : windows) {
|
|
||||||
if (w.getDrawable() == pClosedWindow->getDrawable())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (isNeighbor(&w, pClosedWindow) && canEatWindow(&w, pClosedWindow)) {
|
PSIBLING->setPosition(PPARENT->getPosition());
|
||||||
neighbor = &w;
|
PSIBLING->setSize(PPARENT->getSize());
|
||||||
break;
|
|
||||||
|
// make the sibling replace the parent
|
||||||
|
PSIBLING->setParentNodeID(PPARENT->getParentNodeID());
|
||||||
|
|
||||||
|
if (PPARENT->getParentNodeID() != 0
|
||||||
|
&& getWindowFromDrawable(PPARENT->getParentNodeID())) {
|
||||||
|
if (getWindowFromDrawable(PPARENT->getParentNodeID())->getChildNodeAID() == PPARENT->getDrawable()) {
|
||||||
|
getWindowFromDrawable(PPARENT->getParentNodeID())->setChildNodeAID(PSIBLING->getDrawable());
|
||||||
|
} else {
|
||||||
|
getWindowFromDrawable(PPARENT->getParentNodeID())->setChildNodeBID(PSIBLING->getDrawable());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!neighbor)
|
// Make the sibling eat the closed window
|
||||||
return; // No neighbor. Don't update, easy.
|
PSIBLING->setDirtyRecursive(true);
|
||||||
|
PSIBLING->recalcSizePosRecursive();
|
||||||
|
|
||||||
// update neighbor to "eat" closed.
|
// Remove the parent
|
||||||
eatWindow(neighbor, pClosedWindow);
|
removeWindowFromVectorSafe(PPARENT->getDrawable());
|
||||||
|
|
||||||
neighbor->setDirty(true);
|
if (findWindowAtCursor())
|
||||||
setFocusedWindow(neighbor->getDrawable()); // Set focus. :)
|
setFocusedWindow(findWindowAtCursor()->getDrawable()); // Set focus. :)
|
||||||
}
|
}
|
||||||
|
|
||||||
CWindow* CWindowManager::getNeighborInDir(char dir) {
|
CWindow* CWindowManager::getNeighborInDir(char dir) {
|
||||||
|
@ -717,9 +711,6 @@ void CWindowManager::changeWorkspaceByID(int ID) {
|
||||||
activeWorkspaces[workspace.getMonitor()] = workspace.getID();
|
activeWorkspaces[workspace.getMonitor()] = workspace.getID();
|
||||||
LastWindow = -1;
|
LastWindow = -1;
|
||||||
|
|
||||||
// Perform a sanity check for the new workspace
|
|
||||||
performSanityCheckForWorkspace(ID);
|
|
||||||
|
|
||||||
// Update bar info
|
// Update bar info
|
||||||
updateBarInfo();
|
updateBarInfo();
|
||||||
|
|
||||||
|
@ -738,9 +729,6 @@ void CWindowManager::changeWorkspaceByID(int ID) {
|
||||||
activeWorkspaces[MONITOR->ID] = workspaces[workspaces.size() - 1].getID();
|
activeWorkspaces[MONITOR->ID] = workspaces[workspaces.size() - 1].getID();
|
||||||
LastWindow = -1;
|
LastWindow = -1;
|
||||||
|
|
||||||
// Perform a sanity check for the new workspace
|
|
||||||
performSanityCheckForWorkspace(ID);
|
|
||||||
|
|
||||||
// Update bar info
|
// Update bar info
|
||||||
updateBarInfo();
|
updateBarInfo();
|
||||||
|
|
||||||
|
|
|
@ -37,14 +37,13 @@ public:
|
||||||
CStatusBar statusBar;
|
CStatusBar statusBar;
|
||||||
std::thread* barThread;
|
std::thread* barThread;
|
||||||
|
|
||||||
CWindow* getWindowFromDrawable(xcb_drawable_t);
|
CWindow* getWindowFromDrawable(int64_t);
|
||||||
void addWindowToVectorSafe(CWindow);
|
void addWindowToVectorSafe(CWindow);
|
||||||
void removeWindowFromVectorSafe(xcb_drawable_t);
|
void removeWindowFromVectorSafe(xcb_drawable_t);
|
||||||
|
|
||||||
void setupManager();
|
void setupManager();
|
||||||
bool handleEvent();
|
bool handleEvent();
|
||||||
void refreshDirtyWindows();
|
void refreshDirtyWindows();
|
||||||
void performSanityCheckForWorkspace(int);
|
|
||||||
|
|
||||||
void setFocusedWindow(xcb_drawable_t);
|
void setFocusedWindow(xcb_drawable_t);
|
||||||
|
|
||||||
|
@ -65,6 +64,9 @@ public:
|
||||||
SMonitor* getMonitorFromWindow(CWindow*);
|
SMonitor* getMonitorFromWindow(CWindow*);
|
||||||
SMonitor* getMonitorFromCursor();
|
SMonitor* getMonitorFromCursor();
|
||||||
|
|
||||||
|
// finds a window that's tiled at cursor.
|
||||||
|
CWindow* findWindowAtCursor();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Internal WM functions that don't have to be exposed
|
// Internal WM functions that don't have to be exposed
|
||||||
|
@ -77,7 +79,6 @@ public:
|
||||||
bool isNeighbor(CWindow* a, CWindow* b);
|
bool isNeighbor(CWindow* a, CWindow* b);
|
||||||
void calculateNewTileSetOldTile(CWindow* pWindow);
|
void calculateNewTileSetOldTile(CWindow* pWindow);
|
||||||
void calculateNewFloatingWindow(CWindow* pWindow);
|
void calculateNewFloatingWindow(CWindow* pWindow);
|
||||||
CWindow* findWindowAtCursor();
|
|
||||||
void setEffectiveSizePosUsingConfig(CWindow* pWindow);
|
void setEffectiveSizePosUsingConfig(CWindow* pWindow);
|
||||||
void cleanupUnusedWorkspaces();
|
void cleanupUnusedWorkspaces();
|
||||||
xcb_visualtype_t* setupColors();
|
xcb_visualtype_t* setupColors();
|
||||||
|
|
Loading…
Reference in a new issue