layout: rethonk layouts from the ground up (#12890)
Rewrites layouts to be much smaller, and deal with much less annoying BS. Improves the overall architecture, unifies handling of pseudotiling, and various other improvements.
This commit is contained in:
parent
51f8849e54
commit
723870337f
82 changed files with 8431 additions and 5527 deletions
|
|
@ -3,6 +3,8 @@
|
|||
#include <hyprutils/animation/AnimatedVariable.hpp>
|
||||
#include <re2/re2.h>
|
||||
|
||||
#include "Group.hpp"
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
|
@ -37,12 +39,15 @@
|
|||
#include "../../helpers/math/Expression.hpp"
|
||||
#include "../../managers/XWaylandManager.hpp"
|
||||
#include "../../render/Renderer.hpp"
|
||||
#include "../../managers/LayoutManager.hpp"
|
||||
#include "../../managers/HookSystemManager.hpp"
|
||||
#include "../../managers/EventManager.hpp"
|
||||
#include "../../managers/input/InputManager.hpp"
|
||||
#include "../../managers/PointerManager.hpp"
|
||||
#include "../../managers/animation/DesktopAnimationManager.hpp"
|
||||
#include "../../layout/space/Space.hpp"
|
||||
#include "../../layout/LayoutManager.hpp"
|
||||
#include "../../layout/target/WindowTarget.hpp"
|
||||
#include "../../layout/target/WindowGroupTarget.hpp"
|
||||
|
||||
#include <hyprutils/string/String.hpp>
|
||||
|
||||
|
|
@ -57,6 +62,9 @@ using namespace Desktop::View;
|
|||
static uint64_t windowIDCounter = 0x18000000;
|
||||
|
||||
//
|
||||
#define COMMA ,
|
||||
//
|
||||
|
||||
PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
|
||||
PHLWINDOW pWindow = SP<CWindow>(new CWindow(surface));
|
||||
|
||||
|
|
@ -79,6 +87,8 @@ PHLWINDOW CWindow::create(SP<CXWaylandSurface> surface) {
|
|||
pWindow->addWindowDeco(makeUnique<CHyprDropShadowDecoration>(pWindow));
|
||||
pWindow->addWindowDeco(makeUnique<CHyprBorderDecoration>(pWindow));
|
||||
|
||||
pWindow->m_target = Layout::CWindowTarget::create(pWindow);
|
||||
|
||||
return pWindow;
|
||||
}
|
||||
|
||||
|
|
@ -104,6 +114,8 @@ PHLWINDOW CWindow::create(SP<CXDGSurfaceResource> resource) {
|
|||
pWindow->addWindowDeco(makeUnique<CHyprDropShadowDecoration>(pWindow));
|
||||
pWindow->addWindowDeco(makeUnique<CHyprBorderDecoration>(pWindow));
|
||||
|
||||
pWindow->m_target = Layout::CWindowTarget::create(pWindow);
|
||||
|
||||
pWindow->wlSurface()->assign(pWindow->m_xdgSurface->m_surface.lock(), pWindow);
|
||||
|
||||
return pWindow;
|
||||
|
|
@ -263,23 +275,24 @@ CBox CWindow::getWindowIdealBoundingBoxIgnoreReserved() {
|
|||
return CBox{sc<int>(POS.x), sc<int>(POS.y), sc<int>(SIZE.x), sc<int>(SIZE.y)};
|
||||
}
|
||||
|
||||
// get work area
|
||||
const auto WORKAREA = g_pLayoutManager->getCurrentLayout()->workAreaOnWorkspace(m_workspace);
|
||||
const auto RESERVED = CReservedArea{PMONITOR->logicalBox(), WORKAREA};
|
||||
// fucker fucking fuck
|
||||
const auto WORKAREA = m_workspace->m_space->workArea();
|
||||
const auto& RESERVED = PMONITOR->m_reservedArea;
|
||||
|
||||
if (DELTALESSTHAN(POS.y - PMONITOR->m_position.y, RESERVED.top(), 1)) {
|
||||
POS.y = PMONITOR->m_position.y;
|
||||
SIZE.y += RESERVED.top();
|
||||
}
|
||||
if (DELTALESSTHAN(POS.x - PMONITOR->m_position.x, RESERVED.left(), 1)) {
|
||||
POS.x = PMONITOR->m_position.x;
|
||||
if (DELTALESSTHAN(POS.x, WORKAREA.x, 1)) {
|
||||
POS.x -= RESERVED.left();
|
||||
SIZE.x += RESERVED.left();
|
||||
}
|
||||
|
||||
if (DELTALESSTHAN(POS.x + SIZE.x - PMONITOR->m_position.x, PMONITOR->m_size.x - RESERVED.right(), 1))
|
||||
if (DELTALESSTHAN(POS.y, WORKAREA.y, 1)) {
|
||||
POS.y -= RESERVED.top();
|
||||
SIZE.y += RESERVED.top();
|
||||
}
|
||||
|
||||
if (DELTALESSTHAN(POS.x + SIZE.x, WORKAREA.x + WORKAREA.width, 1))
|
||||
SIZE.x += RESERVED.right();
|
||||
|
||||
if (DELTALESSTHAN(POS.y + SIZE.y - PMONITOR->m_position.y, PMONITOR->m_size.y - RESERVED.bottom(), 1))
|
||||
if (DELTALESSTHAN(POS.y + SIZE.y, WORKAREA.y + WORKAREA.height, 1))
|
||||
SIZE.y += RESERVED.bottom();
|
||||
|
||||
return CBox{sc<int>(POS.x), sc<int>(POS.y), sc<int>(SIZE.x), sc<int>(SIZE.y)};
|
||||
|
|
@ -357,14 +370,18 @@ void CWindow::addWindowDeco(UP<IHyprWindowDecoration> deco) {
|
|||
m_windowDecorations.emplace_back(std::move(deco));
|
||||
g_pDecorationPositioner->forceRecalcFor(m_self.lock());
|
||||
updateWindowDecos();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(m_self.lock());
|
||||
|
||||
if (layoutTarget())
|
||||
layoutTarget()->recalc();
|
||||
}
|
||||
|
||||
void CWindow::removeWindowDeco(IHyprWindowDecoration* deco) {
|
||||
m_decosToRemove.push_back(deco);
|
||||
g_pDecorationPositioner->forceRecalcFor(m_self.lock());
|
||||
updateWindowDecos();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(m_self.lock());
|
||||
|
||||
if (layoutTarget())
|
||||
layoutTarget()->recalc();
|
||||
}
|
||||
|
||||
void CWindow::uncacheWindowDecos() {
|
||||
|
|
@ -495,11 +512,9 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) {
|
|||
|
||||
OLDWORKSPACE->updateWindows();
|
||||
OLDWORKSPACE->updateWindowData();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(OLDWORKSPACE->monitorID());
|
||||
|
||||
pWorkspace->updateWindows();
|
||||
pWorkspace->updateWindowData();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
|
||||
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
|
|
@ -591,7 +606,7 @@ void CWindow::onUnmap() {
|
|||
m_workspace->updateWindows();
|
||||
m_workspace->updateWindowData();
|
||||
}
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
|
||||
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
m_workspace.reset();
|
||||
|
|
@ -723,311 +738,6 @@ bool CWindow::hasPopupAt(const Vector2D& pos) {
|
|||
return popup && popup->wlSurface()->resource();
|
||||
}
|
||||
|
||||
void CWindow::applyGroupRules() {
|
||||
if ((m_groupRules & GROUP_SET && m_firstMap) || m_groupRules & GROUP_SET_ALWAYS)
|
||||
createGroup();
|
||||
|
||||
if (m_groupData.pNextWindow.lock() && ((m_groupRules & GROUP_LOCK && m_firstMap) || m_groupRules & GROUP_LOCK_ALWAYS))
|
||||
getGroupHead()->m_groupData.locked = true;
|
||||
}
|
||||
|
||||
void CWindow::createGroup() {
|
||||
if (m_groupData.deny) {
|
||||
Log::logger->log(Log::DEBUG, "createGroup: window:{:x},title:{} is denied as a group, ignored", rc<uintptr_t>(this), this->m_title);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_groupData.pNextWindow.expired()) {
|
||||
m_groupData.pNextWindow = m_self;
|
||||
m_groupData.head = true;
|
||||
m_groupData.locked = false;
|
||||
m_groupData.deny = false;
|
||||
|
||||
addWindowDeco(makeUnique<CHyprGroupBarDecoration>(m_self.lock()));
|
||||
|
||||
if (m_workspace) {
|
||||
m_workspace->updateWindows();
|
||||
m_workspace->updateWindowData();
|
||||
}
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "togglegroup", .data = std::format("1,{:x}", rc<uintptr_t>(this))});
|
||||
}
|
||||
|
||||
m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||
}
|
||||
|
||||
void CWindow::destroyGroup() {
|
||||
if (m_groupData.pNextWindow == m_self) {
|
||||
if (m_groupRules & GROUP_SET_ALWAYS) {
|
||||
Log::logger->log(Log::DEBUG, "destoryGroup: window:{:x},title:{} has rule [group set always], ignored", rc<uintptr_t>(this), this->m_title);
|
||||
return;
|
||||
}
|
||||
m_groupData.pNextWindow.reset();
|
||||
m_groupData.head = false;
|
||||
updateWindowDecos();
|
||||
if (m_workspace) {
|
||||
m_workspace->updateWindows();
|
||||
m_workspace->updateWindowData();
|
||||
}
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "togglegroup", .data = std::format("0,{:x}", rc<uintptr_t>(this))});
|
||||
m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string addresses;
|
||||
PHLWINDOW curr = m_self.lock();
|
||||
std::vector<PHLWINDOW> members;
|
||||
do {
|
||||
const auto PLASTWIN = curr;
|
||||
curr = curr->m_groupData.pNextWindow.lock();
|
||||
PLASTWIN->m_groupData.pNextWindow.reset();
|
||||
curr->setHidden(false);
|
||||
members.push_back(curr);
|
||||
|
||||
addresses += std::format("{:x},", rc<uintptr_t>(curr.get()));
|
||||
} while (curr.get() != this);
|
||||
|
||||
for (auto const& w : members) {
|
||||
if (w->m_groupData.head)
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(curr);
|
||||
w->m_groupData.head = false;
|
||||
}
|
||||
|
||||
const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_groupsLocked;
|
||||
g_pKeybindManager->m_groupsLocked = true;
|
||||
for (auto const& w : members) {
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(w);
|
||||
w->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||
w->updateWindowDecos();
|
||||
}
|
||||
g_pKeybindManager->m_groupsLocked = GROUPSLOCKEDPREV;
|
||||
|
||||
if (m_workspace) {
|
||||
m_workspace->updateWindows();
|
||||
m_workspace->updateWindowData();
|
||||
}
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
if (!addresses.empty())
|
||||
addresses.pop_back();
|
||||
|
||||
m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "togglegroup", .data = std::format("0,{}", addresses)});
|
||||
}
|
||||
|
||||
PHLWINDOW CWindow::getGroupHead() {
|
||||
PHLWINDOW curr = m_self.lock();
|
||||
while (!curr->m_groupData.head)
|
||||
curr = curr->m_groupData.pNextWindow.lock();
|
||||
return curr;
|
||||
}
|
||||
|
||||
PHLWINDOW CWindow::getGroupTail() {
|
||||
PHLWINDOW curr = m_self.lock();
|
||||
while (!curr->m_groupData.pNextWindow->m_groupData.head)
|
||||
curr = curr->m_groupData.pNextWindow.lock();
|
||||
return curr;
|
||||
}
|
||||
|
||||
PHLWINDOW CWindow::getGroupCurrent() {
|
||||
PHLWINDOW curr = m_self.lock();
|
||||
while (curr->isHidden())
|
||||
curr = curr->m_groupData.pNextWindow.lock();
|
||||
return curr;
|
||||
}
|
||||
|
||||
int CWindow::getGroupSize() {
|
||||
int size = 1;
|
||||
PHLWINDOW curr = m_self.lock();
|
||||
while (curr->m_groupData.pNextWindow != m_self) {
|
||||
curr = curr->m_groupData.pNextWindow.lock();
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
bool CWindow::canBeGroupedInto(PHLWINDOW pWindow) {
|
||||
static auto ALLOWGROUPMERGE = CConfigValue<Hyprlang::INT>("group:merge_groups_on_drag");
|
||||
bool isGroup = m_groupData.pNextWindow;
|
||||
bool disallowDragIntoGroup = g_pInputManager->m_wasDraggingWindow && isGroup && !sc<bool>(*ALLOWGROUPMERGE);
|
||||
return !g_pKeybindManager->m_groupsLocked // global group lock disengaged
|
||||
&& ((m_groupRules & GROUP_INVADE && m_firstMap) // window ignore local group locks, or
|
||||
|| (!pWindow->getGroupHead()->m_groupData.locked // target unlocked
|
||||
&& !(m_groupData.pNextWindow.lock() && getGroupHead()->m_groupData.locked))) // source unlocked or isn't group
|
||||
&& !m_groupData.deny // source is not denied entry
|
||||
&& !(m_groupRules & GROUP_BARRED && m_firstMap) // group rule doesn't prevent adding window
|
||||
&& !disallowDragIntoGroup; // config allows groups to be merged
|
||||
}
|
||||
|
||||
PHLWINDOW CWindow::getGroupWindowByIndex(int index) {
|
||||
const int SIZE = getGroupSize();
|
||||
index = ((index % SIZE) + SIZE) % SIZE;
|
||||
PHLWINDOW curr = getGroupHead();
|
||||
while (index > 0) {
|
||||
curr = curr->m_groupData.pNextWindow.lock();
|
||||
index--;
|
||||
}
|
||||
return curr;
|
||||
}
|
||||
|
||||
bool CWindow::hasInGroup(PHLWINDOW w) {
|
||||
PHLWINDOW curr = m_groupData.pNextWindow.lock();
|
||||
while (curr && curr != m_self) {
|
||||
if (curr == w)
|
||||
return true;
|
||||
curr = curr->m_groupData.pNextWindow.lock();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CWindow::setGroupCurrent(PHLWINDOW pWindow) {
|
||||
PHLWINDOW curr = m_groupData.pNextWindow.lock();
|
||||
bool isMember = false;
|
||||
while (curr.get() != this) {
|
||||
if (curr == pWindow) {
|
||||
isMember = true;
|
||||
break;
|
||||
}
|
||||
curr = curr->m_groupData.pNextWindow.lock();
|
||||
}
|
||||
|
||||
if (!isMember && pWindow.get() != this)
|
||||
return;
|
||||
|
||||
const auto PCURRENT = getGroupCurrent();
|
||||
const bool FULLSCREEN = PCURRENT->isFullscreen();
|
||||
const auto WORKSPACE = PCURRENT->m_workspace;
|
||||
const auto MODE = PCURRENT->m_fullscreenState.internal;
|
||||
|
||||
const auto CURRENTISFOCUS = PCURRENT == Desktop::focusState()->window();
|
||||
|
||||
const auto PWINDOWSIZE = PCURRENT->m_realSize->value();
|
||||
const auto PWINDOWPOS = PCURRENT->m_realPosition->value();
|
||||
const auto PWINDOWSIZEGOAL = PCURRENT->m_realSize->goal();
|
||||
const auto PWINDOWPOSGOAL = PCURRENT->m_realPosition->goal();
|
||||
const auto PWINDOWLASTFLOATINGSIZE = PCURRENT->m_lastFloatingSize;
|
||||
const auto PWINDOWLASTFLOATINGPOSITION = PCURRENT->m_lastFloatingPosition;
|
||||
|
||||
if (FULLSCREEN)
|
||||
g_pCompositor->setWindowFullscreenInternal(PCURRENT, FSMODE_NONE);
|
||||
|
||||
PCURRENT->setHidden(true);
|
||||
pWindow->setHidden(false); // can remove m_pLastWindow
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->replaceWindowDataWith(PCURRENT, pWindow);
|
||||
|
||||
if (PCURRENT->m_isFloating) {
|
||||
pWindow->m_realPosition->setValueAndWarp(PWINDOWPOSGOAL);
|
||||
pWindow->m_realSize->setValueAndWarp(PWINDOWSIZEGOAL);
|
||||
pWindow->sendWindowSize();
|
||||
}
|
||||
|
||||
pWindow->m_realPosition->setValue(PWINDOWPOS);
|
||||
pWindow->m_realSize->setValue(PWINDOWSIZE);
|
||||
|
||||
if (FULLSCREEN)
|
||||
g_pCompositor->setWindowFullscreenInternal(pWindow, MODE);
|
||||
|
||||
pWindow->m_lastFloatingSize = PWINDOWLASTFLOATINGSIZE;
|
||||
pWindow->m_lastFloatingPosition = PWINDOWLASTFLOATINGPOSITION;
|
||||
|
||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||
|
||||
if (CURRENTISFOCUS)
|
||||
Desktop::focusState()->rawWindowFocus(pWindow);
|
||||
|
||||
g_pHyprRenderer->damageWindow(pWindow);
|
||||
|
||||
pWindow->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||
m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||
pWindow->updateWindowDecos();
|
||||
}
|
||||
|
||||
void CWindow::insertWindowToGroup(PHLWINDOW pWindow) {
|
||||
const auto BEGINAT = m_self.lock();
|
||||
const auto ENDAT = m_groupData.pNextWindow.lock();
|
||||
|
||||
if (!pWindow->m_groupData.pNextWindow.lock()) {
|
||||
BEGINAT->m_groupData.pNextWindow = pWindow;
|
||||
pWindow->m_groupData.pNextWindow = ENDAT;
|
||||
pWindow->m_groupData.head = false;
|
||||
pWindow->addWindowDeco(makeUnique<CHyprGroupBarDecoration>(pWindow));
|
||||
return;
|
||||
}
|
||||
|
||||
const auto SHEAD = pWindow->getGroupHead();
|
||||
const auto STAIL = pWindow->getGroupTail();
|
||||
|
||||
SHEAD->m_groupData.head = false;
|
||||
BEGINAT->m_groupData.pNextWindow = SHEAD;
|
||||
STAIL->m_groupData.pNextWindow = ENDAT;
|
||||
|
||||
pWindow->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||
m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||
pWindow->updateWindowDecos();
|
||||
}
|
||||
|
||||
PHLWINDOW CWindow::getGroupPrevious() {
|
||||
PHLWINDOW curr = m_groupData.pNextWindow.lock();
|
||||
|
||||
while (curr != m_self && curr->m_groupData.pNextWindow != m_self)
|
||||
curr = curr->m_groupData.pNextWindow.lock();
|
||||
|
||||
return curr;
|
||||
}
|
||||
|
||||
void CWindow::switchWithWindowInGroup(PHLWINDOW pWindow) {
|
||||
if (!m_groupData.pNextWindow.lock() || !pWindow->m_groupData.pNextWindow.lock())
|
||||
return;
|
||||
|
||||
if (m_groupData.pNextWindow.lock() == pWindow) { // A -> this -> pWindow -> B >> A -> pWindow -> this -> B
|
||||
getGroupPrevious()->m_groupData.pNextWindow = pWindow;
|
||||
m_groupData.pNextWindow = pWindow->m_groupData.pNextWindow;
|
||||
pWindow->m_groupData.pNextWindow = m_self;
|
||||
|
||||
} else if (pWindow->m_groupData.pNextWindow == m_self) { // A -> pWindow -> this -> B >> A -> this -> pWindow -> B
|
||||
pWindow->getGroupPrevious()->m_groupData.pNextWindow = m_self;
|
||||
pWindow->m_groupData.pNextWindow = m_groupData.pNextWindow;
|
||||
m_groupData.pNextWindow = pWindow;
|
||||
|
||||
} else { // A -> this -> B | C -> pWindow -> D >> A -> pWindow -> B | C -> this -> D
|
||||
std::swap(m_groupData.pNextWindow, pWindow->m_groupData.pNextWindow);
|
||||
std::swap(getGroupPrevious()->m_groupData.pNextWindow, pWindow->getGroupPrevious()->m_groupData.pNextWindow);
|
||||
}
|
||||
|
||||
std::swap(m_groupData.head, pWindow->m_groupData.head);
|
||||
std::swap(m_groupData.locked, pWindow->m_groupData.locked);
|
||||
|
||||
pWindow->m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||
m_ruleApplicator->propertiesChanged(Desktop::Rule::RULE_PROP_GROUP | Desktop::Rule::RULE_PROP_ON_WORKSPACE);
|
||||
pWindow->updateWindowDecos();
|
||||
}
|
||||
|
||||
void CWindow::updateGroupOutputs() {
|
||||
if (m_groupData.pNextWindow.expired())
|
||||
return;
|
||||
|
||||
PHLWINDOW curr = m_groupData.pNextWindow.lock();
|
||||
|
||||
const auto WS = m_workspace;
|
||||
|
||||
while (curr.get() != this) {
|
||||
curr->m_monitor = m_monitor;
|
||||
curr->moveToWorkspace(WS);
|
||||
|
||||
*curr->m_realPosition = m_realPosition->goal();
|
||||
*curr->m_realSize = m_realSize->goal();
|
||||
|
||||
curr = curr->m_groupData.pNextWindow.lock();
|
||||
}
|
||||
}
|
||||
|
||||
Vector2D CWindow::middle() {
|
||||
return m_realPosition->goal() + m_realSize->goal() / 2.f;
|
||||
}
|
||||
|
|
@ -1148,7 +858,7 @@ void CWindow::setAnimationsToMove() {
|
|||
|
||||
void CWindow::onWorkspaceAnimUpdate() {
|
||||
// clip box for animated offsets
|
||||
if (!m_isFloating || m_pinned || isFullscreen() || m_draggingTiled) {
|
||||
if (!m_isFloating || m_pinned || isFullscreen()) {
|
||||
m_floatingOffset = Vector2D(0, 0);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1326,7 +1036,7 @@ void CWindow::activate(bool force) {
|
|||
if (m_isFloating)
|
||||
g_pCompositor->changeWindowZOrder(m_self.lock(), true);
|
||||
|
||||
Desktop::focusState()->fullWindowFocus(m_self.lock());
|
||||
Desktop::focusState()->fullWindowFocus(m_self.lock(), FOCUS_REASON_DESKTOP_STATE_CHANGE);
|
||||
warpCursor();
|
||||
}
|
||||
|
||||
|
|
@ -1378,7 +1088,8 @@ void CWindow::onUpdateMeta() {
|
|||
if (m_self == Desktop::focusState()->window()) { // if it's the active, let's post an event to update others
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindow", .data = m_class + "," + m_title});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindowv2", .data = std::format("{:x}", rc<uintptr_t>(this))});
|
||||
EMIT_HOOK_EVENT("activeWindow", m_self.lock());
|
||||
|
||||
// no need for a hook event
|
||||
}
|
||||
|
||||
Log::logger->log(Log::DEBUG, "Window {:x} set title to {}", rc<uintptr_t>(this), m_title);
|
||||
|
|
@ -1392,7 +1103,8 @@ void CWindow::onUpdateMeta() {
|
|||
if (m_self == Desktop::focusState()->window()) { // if it's the active, let's post an event to update others
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindow", .data = m_class + "," + m_title});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{.event = "activewindowv2", .data = std::format("{:x}", rc<uintptr_t>(this))});
|
||||
EMIT_HOOK_EVENT("activeWindow", m_self.lock());
|
||||
|
||||
// no need for a hook event
|
||||
}
|
||||
|
||||
Log::logger->log(Log::DEBUG, "Window {:x} set class to {}", rc<uintptr_t>(this), m_class);
|
||||
|
|
@ -1472,7 +1184,7 @@ void CWindow::onX11ConfigureRequest(CBox box) {
|
|||
|
||||
g_pHyprRenderer->damageWindow(m_self.lock());
|
||||
|
||||
if (!m_isFloating || isFullscreen() || g_pInputManager->m_currentlyDraggedWindow == m_self) {
|
||||
if (!m_isFloating || isFullscreen() || g_layoutManager->dragController()->target() == m_self) {
|
||||
sendWindowSize(true);
|
||||
g_pInputManager->refocus();
|
||||
g_pHyprRenderer->damageWindow(m_self.lock());
|
||||
|
|
@ -1689,20 +1401,17 @@ void CWindow::setContentType(NContentType::eContentType contentType) {
|
|||
}
|
||||
|
||||
void CWindow::deactivateGroupMembers() {
|
||||
auto curr = getGroupHead();
|
||||
while (curr) {
|
||||
if (curr != m_self.lock()) {
|
||||
if (!m_group)
|
||||
return;
|
||||
for (const auto& w : m_group->windows()) {
|
||||
if (w != m_self.lock()) {
|
||||
// we don't want to deactivate unfocused xwayland windows
|
||||
// because X is weird, keep the behavior for wayland windows
|
||||
// also its not really needed for xwayland windows
|
||||
// ref: #9760 #9294
|
||||
if (!curr->m_isX11 && curr->m_xdgSurface && curr->m_xdgSurface->m_toplevel)
|
||||
curr->m_xdgSurface->m_toplevel->setActive(false);
|
||||
if (!w->m_isX11 && w->m_xdgSurface && w->m_xdgSurface->m_toplevel)
|
||||
w->m_xdgSurface->m_toplevel->setActive(false);
|
||||
}
|
||||
|
||||
curr = curr->m_groupData.pNextWindow.lock();
|
||||
if (curr == getGroupHead())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1827,21 +1536,13 @@ void CWindow::updateDecorationValues() {
|
|||
|
||||
const bool IS_SHADOWED_BY_MODAL = m_xdgSurface && m_xdgSurface->m_toplevel && m_xdgSurface->m_toplevel->anyChildModal();
|
||||
|
||||
// border
|
||||
const auto RENDERDATA = g_pLayoutManager->getCurrentLayout()->requestRenderHints(m_self.lock());
|
||||
if (RENDERDATA.isBorderGradient)
|
||||
setBorderColor(*RENDERDATA.borderGradient);
|
||||
else {
|
||||
const bool GROUPLOCKED = m_groupData.pNextWindow.lock() ? getGroupHead()->m_groupData.locked : false;
|
||||
if (m_self == Desktop::focusState()->window()) {
|
||||
const auto* const ACTIVECOLOR =
|
||||
!m_groupData.pNextWindow.lock() ? (!m_groupData.deny ? ACTIVECOL : NOGROUPACTIVECOL) : (GROUPLOCKED ? GROUPACTIVELOCKEDCOL : GROUPACTIVECOL);
|
||||
setBorderColor(m_ruleApplicator->activeBorderColor().valueOr(*ACTIVECOLOR));
|
||||
} else {
|
||||
const auto* const INACTIVECOLOR =
|
||||
!m_groupData.pNextWindow.lock() ? (!m_groupData.deny ? INACTIVECOL : NOGROUPINACTIVECOL) : (GROUPLOCKED ? GROUPINACTIVELOCKEDCOL : GROUPINACTIVECOL);
|
||||
setBorderColor(m_ruleApplicator->inactiveBorderColor().valueOr(*INACTIVECOLOR));
|
||||
}
|
||||
const bool GROUPLOCKED = m_group ? m_group->locked() : false;
|
||||
if (m_self == Desktop::focusState()->window()) {
|
||||
const auto* const ACTIVECOLOR = !m_group ? (!(m_groupRules & GROUP_DENY) ? ACTIVECOL : NOGROUPACTIVECOL) : (GROUPLOCKED ? GROUPACTIVELOCKEDCOL : GROUPACTIVECOL);
|
||||
setBorderColor(m_ruleApplicator->activeBorderColor().valueOr(*ACTIVECOLOR));
|
||||
} else {
|
||||
const auto* const INACTIVECOLOR = !m_group ? (!(m_groupRules & GROUP_DENY) ? INACTIVECOL : NOGROUPINACTIVECOL) : (GROUPLOCKED ? GROUPINACTIVELOCKEDCOL : GROUPINACTIVECOL);
|
||||
setBorderColor(m_ruleApplicator->inactiveBorderColor().valueOr(*INACTIVECOLOR));
|
||||
}
|
||||
|
||||
// opacity
|
||||
|
|
@ -1929,6 +1630,7 @@ void CWindow::mapWindow() {
|
|||
static auto PDIMSTRENGTH = CConfigValue<Hyprlang::FLOAT>("decoration:dim_strength");
|
||||
static auto PNEWTAKESOVERFS = CConfigValue<Hyprlang::INT>("misc:on_focus_under_fullscreen");
|
||||
static auto PINITIALWSTRACKING = CConfigValue<Hyprlang::INT>("misc:initial_workspace_tracking");
|
||||
static auto PAUTOGROUP = CConfigValue<Hyprlang::INT>("group:auto_group");
|
||||
|
||||
const auto LAST_FOCUS_WINDOW = Desktop::focusState()->window();
|
||||
const bool IS_LAST_IN_FS = LAST_FOCUS_WINDOW ? LAST_FOCUS_WINDOW->m_fullscreenState.internal != FSMODE_NONE : false;
|
||||
|
|
@ -2053,8 +1755,8 @@ void CWindow::mapWindow() {
|
|||
requestedFSMonitor = MONITOR_INVALID;
|
||||
}
|
||||
|
||||
m_isFloating = m_ruleApplicator->static_.floating.value_or(m_isFloating);
|
||||
m_isPseudotiled = m_ruleApplicator->static_.pseudo.value_or(m_isPseudotiled);
|
||||
m_isFloating = m_ruleApplicator->static_.floating.value_or(m_isFloating);
|
||||
m_target->setPseudo(m_ruleApplicator->static_.pseudo.value_or(m_target->isPseudo()));
|
||||
m_noInitialFocus = m_ruleApplicator->static_.noInitialFocus.value_or(m_noInitialFocus);
|
||||
m_pinned = m_ruleApplicator->static_.pin.value_or(m_pinned);
|
||||
|
||||
|
|
@ -2109,7 +1811,7 @@ void CWindow::mapWindow() {
|
|||
} else if (v == "barred") {
|
||||
m_groupRules |= Desktop::View::GROUP_BARRED;
|
||||
} else if (v == "deny") {
|
||||
m_groupData.deny = true;
|
||||
m_groupRules |= Desktop::View::GROUP_DENY;
|
||||
} else if (v == "override") {
|
||||
// Clear existing rules
|
||||
m_groupRules = Desktop::View::GROUP_OVERRIDE;
|
||||
|
|
@ -2213,9 +1915,9 @@ void CWindow::mapWindow() {
|
|||
m_isFloating = true;
|
||||
|
||||
if (PWORKSPACE->m_defaultPseudo) {
|
||||
m_isPseudotiled = true;
|
||||
CBox desiredGeometry = g_pXWaylandManager->getGeometryForWindow(m_self.lock());
|
||||
m_pseudoSize = Vector2D(desiredGeometry.width, desiredGeometry.height);
|
||||
m_target->setPseudoSize(Vector2D{desiredGeometry.width, desiredGeometry.height});
|
||||
m_target->setPseudo(true);
|
||||
}
|
||||
|
||||
updateWindowData();
|
||||
|
|
@ -2230,43 +1932,29 @@ void CWindow::mapWindow() {
|
|||
g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", std::format("{:x},{},{},{}", m_self.lock(), PWORKSPACE->m_name, m_class, m_title)});
|
||||
EMIT_HOOK_EVENT("openWindowEarly", m_self.lock());
|
||||
|
||||
if (*PAUTOGROUP // auto_group enabled
|
||||
&& Desktop::focusState()->window() // focused window exists
|
||||
&& canBeGroupedInto(Desktop::focusState()->window()->m_group) // we can group
|
||||
&& Desktop::focusState()->window()->m_workspace == m_workspace // workspaces match, we're not opening on another ws
|
||||
&& !isModal() && !(parent() && m_isFloating) && !isX11OverrideRedirect() // not a modal, floating child or X11 OR
|
||||
) {
|
||||
// add to group if we are focused on one
|
||||
Desktop::focusState()->window()->m_group->add(m_self.lock());
|
||||
} else
|
||||
g_layoutManager->newTarget(m_target, m_workspace->m_space);
|
||||
|
||||
if (!m_group && (m_groupRules & GROUP_SET))
|
||||
m_group = CGroup::create({m_self});
|
||||
|
||||
if (m_isFloating) {
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(m_self.lock());
|
||||
m_createdOverFullscreen = true;
|
||||
|
||||
if (!m_ruleApplicator->static_.size.empty()) {
|
||||
const auto COMPUTED = calculateExpression(m_ruleApplicator->static_.size);
|
||||
if (!COMPUTED)
|
||||
Log::logger->log(Log::ERR, "failed to parse {} as an expression", m_ruleApplicator->static_.size);
|
||||
else {
|
||||
*m_realSize = *COMPUTED;
|
||||
setHidden(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_ruleApplicator->static_.position.empty()) {
|
||||
const auto COMPUTED = calculateExpression(m_ruleApplicator->static_.position);
|
||||
if (!COMPUTED)
|
||||
Log::logger->log(Log::ERR, "failed to parse {} as an expression", m_ruleApplicator->static_.position);
|
||||
else {
|
||||
*m_realPosition = *COMPUTED + PMONITOR->m_position;
|
||||
setHidden(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_ruleApplicator->static_.center.value_or(false)) {
|
||||
const auto WORKAREA = PMONITOR->logicalBoxMinusReserved();
|
||||
*m_realPosition = WORKAREA.middle() - m_realSize->goal() / 2.f;
|
||||
}
|
||||
|
||||
// set the pseudo size to the GOAL of our current size
|
||||
// because the windows are animated on RealSize
|
||||
m_pseudoSize = m_realSize->goal();
|
||||
m_target->setPseudoSize(m_realSize->goal());
|
||||
|
||||
g_pCompositor->changeWindowZOrder(m_self.lock(), true);
|
||||
} else {
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(m_self.lock());
|
||||
|
||||
bool setPseudo = false;
|
||||
|
||||
if (!m_ruleApplicator->static_.size.empty()) {
|
||||
|
|
@ -2274,14 +1962,14 @@ void CWindow::mapWindow() {
|
|||
if (!COMPUTED)
|
||||
Log::logger->log(Log::ERR, "failed to parse {} as an expression", m_ruleApplicator->static_.size);
|
||||
else {
|
||||
setPseudo = true;
|
||||
m_pseudoSize = *COMPUTED;
|
||||
setPseudo = true;
|
||||
m_target->setPseudoSize(*COMPUTED);
|
||||
setHidden(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!setPseudo)
|
||||
m_pseudoSize = m_realSize->goal() - Vector2D(10, 10);
|
||||
m_target->setPseudoSize(m_realSize->goal() - Vector2D(10, 10));
|
||||
}
|
||||
|
||||
const auto PFOCUSEDWINDOWPREV = Desktop::focusState()->window();
|
||||
|
|
@ -2311,13 +1999,13 @@ void CWindow::mapWindow() {
|
|||
(!PFORCEFOCUS || PFORCEFOCUS == m_self.lock()) && !g_pInputManager->isConstrained()) {
|
||||
|
||||
// this window should gain focus: if it's grouped, preserve fullscreen state.
|
||||
const bool SAME_GROUP = hasInGroup(LAST_FOCUS_WINDOW);
|
||||
const bool SAME_GROUP = m_group && m_group->has(LAST_FOCUS_WINDOW);
|
||||
|
||||
if (IS_LAST_IN_FS && SAME_GROUP) {
|
||||
Desktop::focusState()->rawWindowFocus(m_self.lock());
|
||||
Desktop::focusState()->rawWindowFocus(m_self.lock(), FOCUS_REASON_NEW_WINDOW);
|
||||
g_pCompositor->setWindowFullscreenInternal(m_self.lock(), LAST_FS_MODE);
|
||||
} else
|
||||
Desktop::focusState()->fullWindowFocus(m_self.lock());
|
||||
Desktop::focusState()->fullWindowFocus(m_self.lock(), FOCUS_REASON_NEW_WINDOW);
|
||||
|
||||
m_activeInactiveAlpha->setValueAndWarp(*PACTIVEALPHA);
|
||||
m_dimPercent->setValueAndWarp(m_ruleApplicator->noDim().valueOrDefault() ? 0.f : *PDIMSTRENGTH);
|
||||
|
|
@ -2358,18 +2046,16 @@ void CWindow::mapWindow() {
|
|||
|
||||
if (workspaceSilent) {
|
||||
if (validMapped(PFOCUSEDWINDOWPREV)) {
|
||||
Desktop::focusState()->rawWindowFocus(PFOCUSEDWINDOWPREV);
|
||||
Desktop::focusState()->rawWindowFocus(PFOCUSEDWINDOWPREV, FOCUS_REASON_NEW_WINDOW);
|
||||
PFOCUSEDWINDOWPREV->updateWindowDecos(); // need to for some reason i cba to find out why
|
||||
} else if (!PFOCUSEDWINDOWPREV)
|
||||
Desktop::focusState()->rawWindowFocus(nullptr);
|
||||
Desktop::focusState()->rawWindowFocus(nullptr, FOCUS_REASON_NEW_WINDOW);
|
||||
}
|
||||
|
||||
// swallow
|
||||
if (SWALLOWER) {
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(SWALLOWER);
|
||||
g_pHyprRenderer->damageWindow(SWALLOWER);
|
||||
g_layoutManager->removeTarget(SWALLOWER->layoutTarget());
|
||||
SWALLOWER->setHidden(true);
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateMonitor(monitorID());
|
||||
}
|
||||
|
||||
m_firstMap = false;
|
||||
|
|
@ -2382,7 +2068,7 @@ void CWindow::mapWindow() {
|
|||
// apply data from default decos. Borders, shadows.
|
||||
g_pDecorationPositioner->forceRecalcFor(m_self.lock());
|
||||
updateWindowDecos();
|
||||
g_pLayoutManager->getCurrentLayout()->recalculateWindow(m_self.lock());
|
||||
layoutTarget()->recalc();
|
||||
|
||||
// do animations
|
||||
g_pDesktopAnimationManager->startAnimation(m_self.lock(), CDesktopAnimationManager::ANIMATION_TYPE_IN);
|
||||
|
|
@ -2454,10 +2140,10 @@ void CWindow::unmapWindow() {
|
|||
m_swallowed->m_currentlySwallowed = false;
|
||||
m_swallowed->setHidden(false);
|
||||
|
||||
if (m_groupData.pNextWindow.lock())
|
||||
if (m_group)
|
||||
m_swallowed->m_groupSwallowed = true; // flag for the swallowed window to be created into the group where it belongs when auto_group = false.
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowCreated(m_swallowed.lock());
|
||||
g_layoutManager->newTarget(m_swallowed->layoutTarget(), m_workspace->m_space);
|
||||
}
|
||||
|
||||
m_swallowed->m_groupSwallowed = false;
|
||||
|
|
@ -2466,7 +2152,7 @@ void CWindow::unmapWindow() {
|
|||
|
||||
bool wasLastWindow = false;
|
||||
PHLWINDOW nextInGroup = [this] -> PHLWINDOW {
|
||||
if (!m_groupData.pNextWindow)
|
||||
if (!m_group)
|
||||
return nullptr;
|
||||
|
||||
// walk the history to find a suitable window
|
||||
|
|
@ -2475,7 +2161,7 @@ void CWindow::unmapWindow() {
|
|||
if (!w || !w->m_isMapped || w == m_self)
|
||||
continue;
|
||||
|
||||
if (!hasInGroup(w.lock()))
|
||||
if (!m_group->has(w.lock()))
|
||||
continue;
|
||||
|
||||
return w.lock();
|
||||
|
|
@ -2491,7 +2177,7 @@ void CWindow::unmapWindow() {
|
|||
g_pInputManager->releaseAllMouseButtons();
|
||||
}
|
||||
|
||||
if (m_self.lock() == g_pInputManager->m_currentlyDraggedWindow.lock())
|
||||
if (m_self.lock() == g_layoutManager->dragController()->target())
|
||||
CKeybindManager::changeMouseBindMode(MBIND_INVALID);
|
||||
|
||||
// remove the fullscreen window status from workspace if we closed it
|
||||
|
|
@ -2500,7 +2186,10 @@ void CWindow::unmapWindow() {
|
|||
if (PWORKSPACE->m_hasFullscreenWindow && isFullscreen())
|
||||
PWORKSPACE->m_hasFullscreenWindow = false;
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(m_self.lock());
|
||||
if (m_group)
|
||||
m_group->remove(m_self.lock());
|
||||
|
||||
g_layoutManager->removeTarget(m_target);
|
||||
|
||||
g_pHyprRenderer->damageWindow(m_self.lock());
|
||||
|
||||
|
|
@ -2516,17 +2205,20 @@ void CWindow::unmapWindow() {
|
|||
if (*FOCUSONCLOSE)
|
||||
candidate = (g_pCompositor->vectorToWindowUnified(g_pInputManager->getMouseCoordsInternal(),
|
||||
Desktop::View::RESERVED_EXTENTS | Desktop::View::INPUT_EXTENTS | Desktop::View::ALLOW_FLOATING));
|
||||
else
|
||||
candidate = g_pLayoutManager->getCurrentLayout()->getNextWindowCandidate(m_self.lock());
|
||||
else {
|
||||
const auto CAND = g_layoutManager->getNextCandidate(m_workspace->m_space, layoutTarget());
|
||||
if (CAND)
|
||||
candidate = CAND->window();
|
||||
}
|
||||
}
|
||||
|
||||
Log::logger->log(Log::DEBUG, "On closed window, new focused candidate is {}", candidate);
|
||||
|
||||
if (candidate != Desktop::focusState()->window() && candidate) {
|
||||
if (candidate == nextInGroup)
|
||||
Desktop::focusState()->rawWindowFocus(candidate);
|
||||
Desktop::focusState()->rawWindowFocus(candidate, FOCUS_REASON_DESKTOP_STATE_CHANGE);
|
||||
else
|
||||
Desktop::focusState()->fullWindowFocus(candidate);
|
||||
Desktop::focusState()->fullWindowFocus(candidate, FOCUS_REASON_DESKTOP_STATE_CHANGE);
|
||||
|
||||
if ((*PEXITRETAINSFS || candidate == nextInGroup) && CURRENTWINDOWFSSTATE)
|
||||
g_pCompositor->setWindowFullscreenInternal(candidate, CURRENTFSMODE);
|
||||
|
|
@ -2541,7 +2233,8 @@ void CWindow::unmapWindow() {
|
|||
if (m_self.lock() == Desktop::focusState()->window() || !Desktop::focusState()->window()) {
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindow", ","});
|
||||
g_pEventManager->postEvent(SHyprIPCEvent{"activewindowv2", ""});
|
||||
EMIT_HOOK_EVENT("activeWindow", PHLWINDOW{nullptr});
|
||||
|
||||
EMIT_HOOK_EVENT("activeWindow", Desktop::View::SWindowActiveEvent{nullptr COMMA FOCUS_REASON_OTHER});
|
||||
}
|
||||
} else {
|
||||
Log::logger->log(Log::DEBUG, "Unmapped was not focused, ignoring a refocus.");
|
||||
|
|
@ -2573,7 +2266,13 @@ void CWindow::commitWindow() {
|
|||
// try to calculate static rules already for any floats
|
||||
m_ruleApplicator->readStaticRules(true);
|
||||
|
||||
Vector2D predSize = g_pLayoutManager->getCurrentLayout()->predictSizeForNewWindow(m_self.lock());
|
||||
const Vector2D predSize = !m_ruleApplicator->static_.floating.value_or(false) // no float rule
|
||||
&& !m_isFloating // not floating
|
||||
&& !parent() // no parents
|
||||
&& !g_pXWaylandManager->shouldBeFloated(m_self.lock(), true) // should not be floated
|
||||
?
|
||||
g_layoutManager->predictSizeForNewTiledTarget().value_or(Vector2D{}) :
|
||||
Vector2D{};
|
||||
|
||||
Log::logger->log(Log::DEBUG, "Layout predicts size {} for {}", predSize, m_self.lock());
|
||||
|
||||
|
|
@ -2634,7 +2333,7 @@ void CWindow::destroyWindow() {
|
|||
|
||||
m_listeners = {};
|
||||
|
||||
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(m_self.lock());
|
||||
g_layoutManager->removeTarget(m_target);
|
||||
|
||||
m_readyToDelete = true;
|
||||
|
||||
|
|
@ -2664,7 +2363,7 @@ void CWindow::activateX11() {
|
|||
if (!m_xwaylandSurface->wantsFocus())
|
||||
return;
|
||||
|
||||
Desktop::focusState()->fullWindowFocus(m_self.lock());
|
||||
Desktop::focusState()->fullWindowFocus(m_self.lock(), FOCUS_REASON_DESKTOP_STATE_CHANGE);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2764,3 +2463,26 @@ std::optional<Vector2D> CWindow::maxSize() {
|
|||
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
SP<Layout::ITarget> CWindow::layoutTarget() {
|
||||
return m_group ? m_group->m_target : m_target;
|
||||
}
|
||||
|
||||
bool CWindow::canBeGroupedInto(SP<CGroup> group) {
|
||||
if (!group)
|
||||
return false;
|
||||
|
||||
if (isX11OverrideRedirect())
|
||||
return false;
|
||||
|
||||
static auto ALLOWGROUPMERGE = CConfigValue<Hyprlang::INT>("group:merge_groups_on_drag");
|
||||
bool isGroup = m_group;
|
||||
bool disallowDragIntoGroup = g_layoutManager->dragController()->wasDraggingWindow() && isGroup && !sc<bool>(*ALLOWGROUPMERGE);
|
||||
return !g_pKeybindManager->m_groupsLocked // global group lock disengaged
|
||||
&& ((m_groupRules & GROUP_INVADE && m_firstMap) // window ignore local group locks, or
|
||||
|| (!group->locked() // target unlocked
|
||||
&& !(m_group && m_group->locked()))) // source unlocked or isn't group
|
||||
&& !(m_groupRules & GROUP_DENY) // source is not denied entry
|
||||
&& !(m_groupRules & GROUP_BARRED && m_firstMap) // group rule doesn't prevent adding window
|
||||
&& !disallowDragIntoGroup; // config allows groups to be merged
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue