algo/scroll: improve directional moves (#13423)
This commit is contained in:
parent
d4d17d5d52
commit
3b7401b065
4 changed files with 117 additions and 54 deletions
|
|
@ -55,12 +55,14 @@ size_t CScrollTapeController::addStrip(float size) {
|
||||||
return m_strips.size() - 1;
|
return m_strips.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CScrollTapeController::insertStrip(size_t afterIndex, float size) {
|
void CScrollTapeController::insertStrip(ssize_t afterIndex, float size) {
|
||||||
if (afterIndex >= m_strips.size()) {
|
if (afterIndex >= sc<ssize_t>(m_strips.size())) {
|
||||||
addStrip(size);
|
addStrip(size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
afterIndex = std::clamp(afterIndex, -1L, sc<ssize_t>(INT32_MAX));
|
||||||
|
|
||||||
SStripData newStrip;
|
SStripData newStrip;
|
||||||
newStrip.size = size;
|
newStrip.size = size;
|
||||||
m_strips.insert(m_strips.begin() + afterIndex + 1, newStrip);
|
m_strips.insert(m_strips.begin() + afterIndex + 1, newStrip);
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ namespace Layout::Tiled {
|
||||||
bool isReversed() const;
|
bool isReversed() const;
|
||||||
|
|
||||||
size_t addStrip(float size = 1.0F);
|
size_t addStrip(float size = 1.0F);
|
||||||
void insertStrip(size_t afterIndex, float size = 1.0F);
|
void insertStrip(ssize_t afterIndex, float size = 1.0F);
|
||||||
void removeStrip(size_t index);
|
void removeStrip(size_t index);
|
||||||
size_t stripCount() const;
|
size_t stripCount() const;
|
||||||
SStripData& getStrip(size_t index);
|
SStripData& getStrip(size_t index);
|
||||||
|
|
|
||||||
|
|
@ -247,24 +247,28 @@ void SColumnData::remove(SP<ITarget> t) {
|
||||||
scrollingData->remove(self.lock());
|
scrollingData->remove(self.lock());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SColumnData::up(SP<SScrollingTargetData> w) {
|
bool SColumnData::up(SP<SScrollingTargetData> w) {
|
||||||
for (size_t i = 1; i < targetDatas.size(); ++i) {
|
for (size_t i = 1; i < targetDatas.size(); ++i) {
|
||||||
if (targetDatas[i] != w)
|
if (targetDatas[i] != w)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::swap(targetDatas[i], targetDatas[i - 1]);
|
std::swap(targetDatas[i], targetDatas[i - 1]);
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SColumnData::down(SP<SScrollingTargetData> w) {
|
bool SColumnData::down(SP<SScrollingTargetData> w) {
|
||||||
for (size_t i = 0; i < targetDatas.size() - 1; ++i) {
|
for (size_t i = 0; i < targetDatas.size() - 1; ++i) {
|
||||||
if (targetDatas[i] != w)
|
if (targetDatas[i] != w)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::swap(targetDatas[i], targetDatas[i + 1]);
|
std::swap(targetDatas[i], targetDatas[i + 1]);
|
||||||
break;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SP<SScrollingTargetData> SColumnData::next(SP<SScrollingTargetData> w) {
|
SP<SScrollingTargetData> SColumnData::next(SP<SScrollingTargetData> w) {
|
||||||
|
|
@ -845,61 +849,118 @@ void CScrollingAlgorithm::moveTargetTo(SP<ITarget> t, Math::eDirection dir, bool
|
||||||
if (!DATA)
|
if (!DATA)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto TAPE_DIR = getDynamicDirection();
|
|
||||||
const auto CURRENT_COL = DATA->column.lock();
|
const auto CURRENT_COL = DATA->column.lock();
|
||||||
const auto current_idx = m_scrollingData->idx(CURRENT_COL);
|
const auto current_idx = m_scrollingData->idx(CURRENT_COL);
|
||||||
|
|
||||||
if (dir == Math::DIRECTION_LEFT) {
|
auto rotateDir = [this](Math::eDirection dir) -> Math::eDirection {
|
||||||
const auto COL = m_scrollingData->prev(DATA->column.lock());
|
switch (m_scrollingData->controller->getDirection()) {
|
||||||
|
case SCROLL_DIR_RIGHT: return dir;
|
||||||
|
case SCROLL_DIR_LEFT: {
|
||||||
|
if (dir == Math::DIRECTION_LEFT)
|
||||||
|
return Math::DIRECTION_RIGHT;
|
||||||
|
if (dir == Math::DIRECTION_RIGHT)
|
||||||
|
return Math::DIRECTION_LEFT;
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
case SCROLL_DIR_UP: {
|
||||||
|
switch (dir) {
|
||||||
|
case Math::DIRECTION_UP: return Math::DIRECTION_RIGHT;
|
||||||
|
case Math::DIRECTION_DOWN: return Math::DIRECTION_LEFT;
|
||||||
|
case Math::DIRECTION_LEFT: return Math::DIRECTION_DOWN;
|
||||||
|
case Math::DIRECTION_RIGHT: return Math::DIRECTION_UP;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
// ignore moves to the "origin" when on first column and moving opposite to tape direction
|
return dir;
|
||||||
if (!COL && current_idx == 0 && (TAPE_DIR == SCROLL_DIR_RIGHT || TAPE_DIR == SCROLL_DIR_DOWN))
|
}
|
||||||
return;
|
case SCROLL_DIR_DOWN: {
|
||||||
|
switch (dir) {
|
||||||
|
case Math::DIRECTION_UP: return Math::DIRECTION_LEFT;
|
||||||
|
case Math::DIRECTION_DOWN: return Math::DIRECTION_RIGHT;
|
||||||
|
case Math::DIRECTION_LEFT: return Math::DIRECTION_DOWN;
|
||||||
|
case Math::DIRECTION_RIGHT: return Math::DIRECTION_UP;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
DATA->column->remove(t);
|
return dir;
|
||||||
|
}
|
||||||
if (!COL) {
|
default: break;
|
||||||
const auto NEWCOL = m_scrollingData->add(-1);
|
|
||||||
NEWCOL->add(DATA);
|
|
||||||
m_scrollingData->centerOrFitCol(NEWCOL);
|
|
||||||
} else {
|
|
||||||
if (COL->targetDatas.size() > 0)
|
|
||||||
COL->add(DATA, COL->idxForHeight(g_pInputManager->getMouseCoordsInternal().y));
|
|
||||||
else
|
|
||||||
COL->add(DATA);
|
|
||||||
m_scrollingData->centerOrFitCol(COL);
|
|
||||||
}
|
|
||||||
} else if (dir == Math::DIRECTION_RIGHT) {
|
|
||||||
const auto COL = m_scrollingData->next(DATA->column.lock());
|
|
||||||
|
|
||||||
// ignore moves to the "origin" when on last column and moving opposite to tape direction
|
|
||||||
if (!COL && current_idx == (int64_t)m_scrollingData->columns.size() - 1 && (TAPE_DIR == SCROLL_DIR_LEFT || TAPE_DIR == SCROLL_DIR_UP))
|
|
||||||
return;
|
|
||||||
|
|
||||||
DATA->column->remove(t);
|
|
||||||
|
|
||||||
if (!COL) {
|
|
||||||
// make a new one
|
|
||||||
const auto NEWCOL = m_scrollingData->add();
|
|
||||||
NEWCOL->add(DATA);
|
|
||||||
m_scrollingData->centerOrFitCol(NEWCOL);
|
|
||||||
} else {
|
|
||||||
if (COL->targetDatas.size() > 0)
|
|
||||||
COL->add(DATA, COL->idxForHeight(g_pInputManager->getMouseCoordsInternal().y));
|
|
||||||
else
|
|
||||||
COL->add(DATA);
|
|
||||||
m_scrollingData->centerOrFitCol(COL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (dir == Math::DIRECTION_UP)
|
return dir;
|
||||||
DATA->column->up(DATA);
|
};
|
||||||
else if (dir == Math::DIRECTION_DOWN)
|
|
||||||
DATA->column->down(DATA);
|
const auto ROTATED_DIR = rotateDir(dir);
|
||||||
|
|
||||||
|
auto commenceDir = [&]() -> bool {
|
||||||
|
if (ROTATED_DIR == Math::DIRECTION_LEFT) {
|
||||||
|
const auto COL = m_scrollingData->prev(DATA->column.lock());
|
||||||
|
|
||||||
|
// ignore moves to the origin if we are alone
|
||||||
|
if (!COL && current_idx == 0 && DATA->column->targetDatas.size() == 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
DATA->column->remove(t);
|
||||||
|
|
||||||
|
if (!COL) {
|
||||||
|
const auto NEWCOL = m_scrollingData->add(-1);
|
||||||
|
NEWCOL->add(DATA);
|
||||||
|
m_scrollingData->centerOrFitCol(NEWCOL);
|
||||||
|
} else {
|
||||||
|
if (COL->targetDatas.size() > 0)
|
||||||
|
COL->add(DATA, COL->idxForHeight(g_pInputManager->getMouseCoordsInternal().y));
|
||||||
|
else
|
||||||
|
COL->add(DATA);
|
||||||
|
m_scrollingData->centerOrFitCol(COL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else if (ROTATED_DIR == Math::DIRECTION_RIGHT) {
|
||||||
|
const auto COL = m_scrollingData->next(DATA->column.lock());
|
||||||
|
|
||||||
|
// ignore move to the right when there is no next column and we're alone
|
||||||
|
if (!COL && current_idx == (int64_t)m_scrollingData->columns.size() - 1 && DATA->column->targetDatas.size() == 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
DATA->column->remove(t);
|
||||||
|
|
||||||
|
if (!COL) {
|
||||||
|
// make a new one
|
||||||
|
const auto NEWCOL = m_scrollingData->add();
|
||||||
|
NEWCOL->add(DATA);
|
||||||
|
m_scrollingData->centerOrFitCol(NEWCOL);
|
||||||
|
} else {
|
||||||
|
if (COL->targetDatas.size() > 0)
|
||||||
|
COL->add(DATA, COL->idxForHeight(g_pInputManager->getMouseCoordsInternal().y));
|
||||||
|
else
|
||||||
|
COL->add(DATA);
|
||||||
|
m_scrollingData->centerOrFitCol(COL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else if (ROTATED_DIR == Math::DIRECTION_UP)
|
||||||
|
return DATA->column->up(DATA);
|
||||||
|
else if (ROTATED_DIR == Math::DIRECTION_DOWN)
|
||||||
|
return DATA->column->down(DATA);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!commenceDir()) {
|
||||||
|
// dir wasn't commenced, move to a workspace if possible
|
||||||
|
// with the original dir
|
||||||
|
const auto MONINDIR = g_pCompositor->getMonitorInDirection(m_parent->space()->workspace()->m_monitor.lock(), dir);
|
||||||
|
if (MONINDIR && MONINDIR != m_parent->space()->workspace()->m_monitor && MONINDIR->m_activeWorkspace) {
|
||||||
|
t->assignToSpace(MONINDIR->m_activeWorkspace->m_space);
|
||||||
|
|
||||||
|
m_scrollingData->recalculate();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_scrollingData->recalculate();
|
m_scrollingData->recalculate();
|
||||||
focusTargetUpdate(t);
|
focusTargetUpdate(t);
|
||||||
if (t->window())
|
|
||||||
g_pCompositor->warpCursorTo(t->window()->middle());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::expected<void, std::string> CScrollingAlgorithm::layoutMsg(const std::string_view& sv) {
|
std::expected<void, std::string> CScrollingAlgorithm::layoutMsg(const std::string_view& sv) {
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,8 @@ namespace Layout::Tiled {
|
||||||
// index of lowest target that is above y.
|
// index of lowest target that is above y.
|
||||||
size_t idxForHeight(float y);
|
size_t idxForHeight(float y);
|
||||||
|
|
||||||
void up(SP<SScrollingTargetData> w);
|
bool up(SP<SScrollingTargetData> w);
|
||||||
void down(SP<SScrollingTargetData> w);
|
bool down(SP<SScrollingTargetData> w);
|
||||||
|
|
||||||
SP<SScrollingTargetData> next(SP<SScrollingTargetData> w);
|
SP<SScrollingTargetData> next(SP<SScrollingTargetData> w);
|
||||||
SP<SScrollingTargetData> prev(SP<SScrollingTargetData> w);
|
SP<SScrollingTargetData> prev(SP<SScrollingTargetData> w);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue