layout: add size prediction for initial xdg commits

fixes #4022
This commit is contained in:
Vaxry 2024-02-28 11:45:43 +00:00
parent c198d744b7
commit f4f3aa2e50
7 changed files with 100 additions and 9 deletions

View file

@ -806,7 +806,9 @@ void Events::listener_commitWindow(void* owner, void* data) {
CWindow* PWINDOW = (CWindow*)owner;
if (!PWINDOW->m_bIsX11 && PWINDOW->m_uSurface.xdg->initial_commit) {
wlr_xdg_toplevel_set_size(PWINDOW->m_uSurface.xdg->toplevel, 0, 0);
const auto PREDSIZE = g_pLayoutManager->getCurrentLayout()->predictSizeForNewWindow();
Debug::log(LOG, "Layout predicts size {} for {}", PREDSIZE, PWINDOW);
wlr_xdg_toplevel_set_size(PWINDOW->m_uSurface.xdg->toplevel, PREDSIZE.x, PREDSIZE.y);
return;
}

View file

@ -127,7 +127,13 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
const auto PWINDOW = pNode->pWindow;
// get specific gaps and rules for this workspace,
// if user specified them in config
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID));
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(pNode->workspaceID));
if (!g_pCompositor->windowExists(PWINDOW)) {
Debug::log(ERR, "Node {} holding invalid {}!!", pNode, PWINDOW);
onWindowRemovedTiling(PWINDOW);
return;
}
if (PWINDOW->m_bIsFullscreen && !pNode->ignoreFullscreenChecks)
return;
@ -143,13 +149,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN);
auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT);
if (!g_pCompositor->windowExists(PWINDOW) || !PWINDOW->m_bIsMapped) {
Debug::log(ERR, "Node {} holding invalid {}!!", pNode, PWINDOW);
onWindowRemovedTiling(PWINDOW);
return;
}
CBox nodeBox = pNode->box;
CBox nodeBox = pNode->box;
nodeBox.round();
PWINDOW->m_vSize = nodeBox.size();
@ -1093,3 +1093,53 @@ void CHyprDwindleLayout::onEnable() {
void CHyprDwindleLayout::onDisable() {
m_lDwindleNodesData.clear();
}
Vector2D CHyprDwindleLayout::predictSizeForNewWindow() {
if (!g_pCompositor->m_pLastMonitor)
return {};
// get window candidate
CWindow* candidate = g_pCompositor->m_pLastWindow;
if (!candidate)
candidate = g_pCompositor->getFirstWindowOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace);
// create a fake node
SDwindleNodeData node;
if (!candidate)
return g_pCompositor->m_pLastMonitor->vecSize;
else {
const auto PNODE = getNodeFromWindow(candidate);
if (!PNODE)
return {};
node = *PNODE;
node.pWindow = nullptr;
CBox box = PNODE->box;
static auto* const PSMARTSPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:smart_split");
static auto* const PPRESERVESPLIT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:preserve_split");
static auto* const PFLMULT = (Hyprlang::FLOAT* const*)g_pConfigManager->getConfigValuePtr("dwindle:split_width_multiplier");
bool splitTop = false;
if (**PPRESERVESPLIT == 0 && **PSMARTSPLIT == 0)
splitTop = box.h * **PFLMULT > box.w;
const auto SPLITSIDE = !splitTop;
if (SPLITSIDE)
node.box = {{}, {box.w / 2.0, box.h}};
else
node.box = {{}, {box.w, box.h / 2.0}};
// TODO: make this better and more accurate
return node.box.size();
}
return {};
}

View file

@ -59,6 +59,7 @@ class CHyprDwindleLayout : public IHyprLayout {
virtual void alterSplitRatio(CWindow*, float, bool);
virtual std::string getLayoutName();
virtual void replaceWindowDataWith(CWindow* from, CWindow* to);
virtual Vector2D predictSizeForNewWindow();
virtual void onEnable();
virtual void onDisable();

View file

@ -593,4 +593,8 @@ void IHyprLayout::requestFocusForWindow(CWindow* pWindow) {
g_pCompositor->focusWindow(pWindow);
}
Vector2D IHyprLayout::predictSizeForNewWindow() {
return Vector2D{};
}
IHyprLayout::~IHyprLayout() {}

View file

@ -181,6 +181,12 @@ class IHyprLayout {
*/
virtual void requestFocusForWindow(CWindow*);
/*
Called to predict the size of a newly opened window to send it a configure.
Return 0,0 if unpredictable
*/
virtual Vector2D predictSizeForNewWindow();
private:
Vector2D m_vBeginDragXY;
Vector2D m_vLastDragXY;

View file

@ -1459,6 +1459,33 @@ void CHyprMasterLayout::replaceWindowDataWith(CWindow* from, CWindow* to) {
applyNodeDataToWindow(PNODE);
}
Vector2D CHyprMasterLayout::predictSizeForNewWindow() {
static auto* const PNEWISMASTER = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:new_is_master");
if (!g_pCompositor->m_pLastMonitor)
return {};
const int NODES = getNodesOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace);
if (NODES <= 0)
return g_pCompositor->m_pLastMonitor->vecSize;
const auto MASTER = getMasterNodeOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace);
if (!MASTER) // wtf
return {};
if (*PNEWISMASTER) {
return MASTER->size;
} else {
const auto SLAVES = NODES - getMastersOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace);
// TODO: make this better
return {g_pCompositor->m_pLastMonitor->vecSize.x - MASTER->size.x, g_pCompositor->m_pLastMonitor->vecSize.y / (SLAVES + 1)};
}
return {};
}
void CHyprMasterLayout::onEnable() {
for (auto& w : g_pCompositor->m_vWindows) {
if (w->m_bIsFloating || !w->m_bIsMapped || w->isHidden())

View file

@ -65,6 +65,7 @@ class CHyprMasterLayout : public IHyprLayout {
virtual void alterSplitRatio(CWindow*, float, bool);
virtual std::string getLayoutName();
virtual void replaceWindowDataWith(CWindow* from, CWindow* to);
virtual Vector2D predictSizeForNewWindow();
virtual void onEnable();
virtual void onDisable();