Skip to content

Commit

Permalink
master: Fix master layout window focus and scroll (#5074)
Browse files Browse the repository at this point in the history
* fix master switch window scrolling

* fix some more dispatchers and remove some duplicate code

* refactor and remove duplicate code

* fix focusmonitor: #5006 (comment)

* change check
  • Loading branch information
thejch authored Mar 13, 2024
1 parent 6c53d4d commit 7ea555d
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 63 deletions.
5 changes: 5 additions & 0 deletions src/Compositor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2297,6 +2297,11 @@ void CCompositor::setWindowFullscreen(CWindow* pWindow, bool on, eFullscreenMode
return;
}

if (pWindow->m_bIsFullscreen == on) {
Debug::log(LOG, "Window is already in the required fullscreen state");
return;
}

const auto PMONITOR = getMonitorFromID(pWindow->m_iMonitorID);

const auto PWORKSPACE = getWorkspaceByID(pWindow->m_iWorkspaceID);
Expand Down
87 changes: 28 additions & 59 deletions src/layout/MasterLayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,8 +245,7 @@ void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {

pWindow->updateSpecialRenderData();

if (pWindow->m_bIsFullscreen)
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);

if (PNODE->isMaster && (MASTERSLEFT <= 1 || *SMALLSPLIT == 1)) {
// find a new master from top of the list
Expand Down Expand Up @@ -1017,8 +1016,6 @@ void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
if (!PNODE2 || !PNODE)
return;

const auto inheritFullscreen = prepareLoseFocus(pWindow);

if (PNODE->workspaceID != PNODE2->workspaceID) {
std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID);
std::swap(pWindow2->m_iWorkspaceID, pWindow->m_iWorkspaceID);
Expand All @@ -1034,8 +1031,6 @@ void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {

g_pHyprRenderer->damageWindow(pWindow);
g_pHyprRenderer->damageWindow(pWindow2);

prepareNewFocus(pWindow2, inheritFullscreen);
}

void CHyprMasterLayout::alterSplitRatio(CWindow* pWindow, float ratio, bool exact) {
Expand Down Expand Up @@ -1076,35 +1071,27 @@ CWindow* CHyprMasterLayout::getNextWindow(CWindow* pWindow, bool next) {
return CANDIDATE == nodes.end() ? nullptr : CANDIDATE->pWindow;
}

bool CHyprMasterLayout::prepareLoseFocus(CWindow* pWindow) {
if (!pWindow)
return false;

//if the current window is fullscreen, make it normal again if we are about to lose focus
if (pWindow->m_bIsFullscreen) {
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
static auto INHERIT = CConfigValue<Hyprlang::INT>("master:inherit_fullscreen");
return *INHERIT == 1;
}

return false;
}

void CHyprMasterLayout::prepareNewFocus(CWindow* pWindow, bool inheritFullscreen) {
if (!pWindow)
return;

if (inheritFullscreen)
g_pCompositor->setWindowFullscreen(pWindow, true, g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID)->m_efFullscreenMode);
}

std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::string message) {
auto switchToWindow = [&](CWindow* PWINDOWTOCHANGETO) {
if (!g_pCompositor->windowValidMapped(PWINDOWTOCHANGETO))
return;

g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
g_pCompositor->warpCursorTo(PWINDOWTOCHANGETO->middle());
if (header.pWindow->m_bIsFullscreen) {
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(header.pWindow->m_iWorkspaceID);
const auto FSMODE = PWORKSPACE->m_efFullscreenMode;
static auto INHERITFULLSCREEN = CConfigValue<Hyprlang::INT>("master:inherit_fullscreen");
g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL);
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
if (*INHERITFULLSCREEN)
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
} else {
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
g_pCompositor->warpCursorTo(PWINDOWTOCHANGETO->middle());
}

g_pInputManager->m_pForcedFocus = PWINDOWTOCHANGETO;
g_pInputManager->simulateMouseMovement();
g_pInputManager->m_pForcedFocus = nullptr;
};

CVarList vars(message, 0, ' ');
Expand Down Expand Up @@ -1138,23 +1125,19 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
const auto NEWCHILD = PMASTER->pWindow;

if (PMASTER->pWindow != PWINDOW) {
const auto NEWMASTER = PWINDOW;
const bool newFocusToChild = vars.size() >= 2 && vars[1] == "child";
const bool inheritFullscreen = prepareLoseFocus(NEWMASTER);
const auto NEWMASTER = PWINDOW;
const bool newFocusToChild = vars.size() >= 2 && vars[1] == "child";
switchWindows(NEWMASTER, NEWCHILD);
const auto NEWFOCUS = newFocusToChild ? NEWCHILD : NEWMASTER;
switchToWindow(NEWFOCUS);
prepareNewFocus(NEWFOCUS, inheritFullscreen);
} else {
for (auto& n : m_lMasterNodesData) {
if (n.workspaceID == PMASTER->workspaceID && !n.isMaster) {
const auto NEWMASTER = n.pWindow;
const bool inheritFullscreen = prepareLoseFocus(NEWCHILD);
const auto NEWMASTER = n.pWindow;
switchWindows(NEWMASTER, NEWCHILD);
const bool newFocusToMaster = vars.size() >= 2 && vars[1] == "master";
const auto NEWFOCUS = newFocusToMaster ? NEWMASTER : NEWCHILD;
switchToWindow(NEWFOCUS);
prepareNewFocus(NEWFOCUS, inheritFullscreen);
break;
}
}
Expand All @@ -1172,24 +1155,20 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
if (!PWINDOW)
return 0;

const bool inheritFullscreen = prepareLoseFocus(PWINDOW);

const auto PMASTER = getMasterNodeOnWorkspace(PWINDOW->m_iWorkspaceID);

if (!PMASTER)
return 0;

if (PMASTER->pWindow != PWINDOW) {
switchToWindow(PMASTER->pWindow);
prepareNewFocus(PMASTER->pWindow, inheritFullscreen);
} else if (vars.size() >= 2 && vars[1] == "master") {
return 0;
} else {
// if master is focused keep master focused (don't do anything)
for (auto& n : m_lMasterNodesData) {
if (n.workspaceID == PMASTER->workspaceID && !n.isMaster) {
switchToWindow(n.pWindow);
prepareNewFocus(n.pWindow, inheritFullscreen);
break;
}
}
Expand All @@ -1202,22 +1181,16 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
if (!PWINDOW)
return 0;

const bool inheritFullscreen = prepareLoseFocus(PWINDOW);

const auto PNEXTWINDOW = getNextWindow(PWINDOW, true);
switchToWindow(PNEXTWINDOW);
prepareNewFocus(PNEXTWINDOW, inheritFullscreen);
} else if (command == "cycleprev") {
const auto PWINDOW = header.pWindow;

if (!PWINDOW)
return 0;

const bool inheritFullscreen = prepareLoseFocus(PWINDOW);

const auto PPREVWINDOW = getNextWindow(PWINDOW, false);
switchToWindow(PPREVWINDOW);
prepareNewFocus(PPREVWINDOW, inheritFullscreen);
} else if (command == "swapnext") {
if (!g_pCompositor->windowValidMapped(header.pWindow))
return 0;
Expand All @@ -1230,9 +1203,9 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, true);

if (PWINDOWTOSWAPWITH) {
prepareLoseFocus(header.pWindow);
g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL);
switchWindows(header.pWindow, PWINDOWTOSWAPWITH);
g_pCompositor->focusWindow(header.pWindow);
switchToWindow(header.pWindow);
}
} else if (command == "swapprev") {
if (!g_pCompositor->windowValidMapped(header.pWindow))
Expand All @@ -1246,9 +1219,9 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, false);

if (PWINDOWTOSWAPWITH) {
prepareLoseFocus(header.pWindow);
g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL);
switchWindows(header.pWindow, PWINDOWTOSWAPWITH);
g_pCompositor->focusWindow(header.pWindow);
switchToWindow(header.pWindow);
}
} else if (command == "addmaster") {
if (!g_pCompositor->windowValidMapped(header.pWindow))
Expand All @@ -1265,7 +1238,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri

if (MASTERS + 2 > WINDOWS && *SMALLSPLIT == 0)
return 0;
prepareLoseFocus(header.pWindow);
g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL);

if (!PNODE || PNODE->isMaster) {
// first non-master node
Expand Down Expand Up @@ -1297,7 +1270,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
if (WINDOWS < 2 || MASTERS < 2)
return 0;

prepareLoseFocus(header.pWindow);
g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL);

if (!PNODE || !PNODE->isMaster) {
// first non-master node
Expand All @@ -1318,7 +1291,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
if (!PWINDOW)
return 0;

prepareLoseFocus(PWINDOW);
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL);

const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->m_iWorkspaceID);

Expand Down Expand Up @@ -1373,9 +1346,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
nd.isMaster = true;
const auto NEWMASTERIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), nd);
m_lMasterNodesData.splice(OLDMASTERIT, m_lMasterNodesData, NEWMASTERIT);
const bool inheritFullscreen = prepareLoseFocus(PWINDOW);
switchToWindow(nd.pWindow);
prepareNewFocus(nd.pWindow, inheritFullscreen);
OLDMASTER->isMaster = false;
m_lMasterNodesData.splice(m_lMasterNodesData.end(), m_lMasterNodesData, OLDMASTERIT);
break;
Expand All @@ -1401,9 +1372,7 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
nd.isMaster = true;
const auto NEWMASTERIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), nd);
m_lMasterNodesData.splice(OLDMASTERIT, m_lMasterNodesData, NEWMASTERIT);
const bool inheritFullscreen = prepareLoseFocus(PWINDOW);
switchToWindow(nd.pWindow);
prepareNewFocus(nd.pWindow, inheritFullscreen);
OLDMASTER->isMaster = false;
m_lMasterNodesData.splice(m_lMasterNodesData.begin(), m_lMasterNodesData, OLDMASTERIT);
break;
Expand All @@ -1430,7 +1399,7 @@ void CHyprMasterLayout::runOrientationCycle(SLayoutMessageHeader& header, CVarLi
if (!PWINDOW)
return;

prepareLoseFocus(PWINDOW);
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL);

const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->m_iWorkspaceID);

Expand Down
4 changes: 1 addition & 3 deletions src/layout/MasterLayout.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,6 @@ class CHyprMasterLayout : public IHyprLayout {
void calculateWorkspace(const int&);
CWindow* getNextWindow(CWindow*, bool);
int getMastersOnWorkspace(const int&);
bool prepareLoseFocus(CWindow*);
void prepareNewFocus(CWindow*, bool inherit_fullscreen);

friend struct SMasterNodeData;
friend struct SMasterWorkspaceData;
Expand All @@ -108,4 +106,4 @@ struct std::formatter<SMasterNodeData*, CharT> : std::formatter<CharT> {
std::format_to(out, ", window: {:x}", node->pWindow);
return std::format_to(out, "]");
}
};
};
6 changes: 5 additions & 1 deletion src/managers/KeybindManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,6 @@ bool CKeybindManager::tryMoveFocusToMonitor(CMonitor* monitor) {
const auto PNEWMAINWORKSPACE = g_pCompositor->getWorkspaceByID(monitor->activeWorkspace);

g_pInputManager->unconstrainMouse();
g_pCompositor->setActiveMonitor(monitor);
PNEWMAINWORKSPACE->rememberPrevWorkspace(PWORKSPACE);

const auto PNEWWORKSPACE = monitor->specialWorkspaceID != 0 ? g_pCompositor->getWorkspaceByID(monitor->specialWorkspaceID) : PNEWMAINWORKSPACE;
Expand All @@ -236,10 +235,15 @@ bool CKeybindManager::tryMoveFocusToMonitor(CMonitor* monitor) {
if (PNEWWINDOW) {
g_pCompositor->focusWindow(PNEWWINDOW);
g_pCompositor->warpCursorTo(PNEWWINDOW->middle());

g_pInputManager->m_pForcedFocus = PNEWWINDOW;
g_pInputManager->simulateMouseMovement();
g_pInputManager->m_pForcedFocus = nullptr;
} else {
g_pCompositor->focusWindow(nullptr);
g_pCompositor->warpCursorTo(monitor->middle());
}
g_pCompositor->setActiveMonitor(monitor);

return true;
}
Expand Down

0 comments on commit 7ea555d

Please sign in to comment.