Refactor placement code

This removes the usage of x11 virtual desktop ids and makes the code a bit
more readable
This commit is contained in:
Xaver Hugl 2022-11-12 21:59:34 +01:00
parent 8197bf8890
commit 147f3509ea

View file

@ -143,34 +143,21 @@ void Placement::placeAtRandom(Window *c, const QRect &area, PlacementPolicy /*ne
c->move(QPoint(tx, ty)); c->move(QPoint(tx, ty));
} }
// TODO: one day, there'll be C++11 ... static inline bool isIrrelevant(const Window *window, const Window *regarding, VirtualDesktop *desktop)
static inline bool isIrrelevant(const Window *client, const Window *regarding, int desktop)
{ {
if (!client->isClient()) { return window == regarding
return true; || !window->isClient()
} || !window->isShown()
if (client == regarding) { || window->isShade()
return true; || !window->isOnDesktop(desktop)
} || !window->isOnCurrentActivity()
if (!client->isShown() || client->isShade()) { || window->isDesktop();
return true; };
}
if (!client->isOnDesktop(desktop)) {
return true;
}
if (!client->isOnCurrentActivity()) {
return true;
}
if (client->isDesktop()) {
return true;
}
return false;
}
/** /**
* Place the client \a c according to a really smart placement algorithm :-) * Place the client \a c according to a really smart placement algorithm :-)
*/ */
void Placement::placeSmart(Window *c, const QRectF &area, PlacementPolicy /*next*/) void Placement::placeSmart(Window *window, const QRectF &area, PlacementPolicy /*next*/)
{ {
Q_ASSERT(area.isValid()); Q_ASSERT(area.isValid());
@ -183,7 +170,7 @@ void Placement::placeSmart(Window *c, const QRectF &area, PlacementPolicy /*next
* with ideas from xfce. * with ideas from xfce.
*/ */
if (!c->frameGeometry().isValid()) { if (!window->frameGeometry().isValid()) {
return; return;
} }
@ -191,7 +178,7 @@ void Placement::placeSmart(Window *c, const QRectF &area, PlacementPolicy /*next
long int overlap, min_overlap = 0; long int overlap, min_overlap = 0;
int x_optimal, y_optimal; int x_optimal, y_optimal;
int possible; int possible;
int desktop = c->desktop() == 0 || c->isOnAllDesktops() ? VirtualDesktopManager::self()->current() : c->desktop(); VirtualDesktop *const desktop = window->isOnCurrentDesktop() ? VirtualDesktopManager::self()->currentDesktop() : window->desktops().front();
int cxl, cxr, cyt, cyb; // temp coords int cxl, cxr, cyt, cyb; // temp coords
int xl, xr, yt, yb; // temp coords int xl, xr, yt, yb; // temp coords
@ -204,8 +191,8 @@ void Placement::placeSmart(Window *c, const QRectF &area, PlacementPolicy /*next
y_optimal = y; y_optimal = y;
// client gabarit // client gabarit
int ch = c->height() - 1; int ch = window->height() - 1;
int cw = c->width() - 1; int cw = window->width() - 1;
bool first_pass = true; // CT lame flag. Don't like it. What else would do? bool first_pass = true; // CT lame flag. Don't like it. What else would do?
@ -225,7 +212,7 @@ void Placement::placeSmart(Window *c, const QRectF &area, PlacementPolicy /*next
cyb = y + ch; cyb = y + ch;
for (auto l = workspace()->stackingOrder().constBegin(); l != workspace()->stackingOrder().constEnd(); ++l) { for (auto l = workspace()->stackingOrder().constBegin(); l != workspace()->stackingOrder().constEnd(); ++l) {
auto client = *l; auto client = *l;
if (isIrrelevant(client, c, desktop)) { if (isIrrelevant(client, window, desktop)) {
continue; continue;
} }
xl = client->x(); xl = client->x();
@ -279,7 +266,7 @@ void Placement::placeSmart(Window *c, const QRectF &area, PlacementPolicy /*next
// compare to the position of each client on the same desk // compare to the position of each client on the same desk
for (auto l = workspace()->stackingOrder().constBegin(); l != workspace()->stackingOrder().constEnd(); ++l) { for (auto l = workspace()->stackingOrder().constBegin(); l != workspace()->stackingOrder().constEnd(); ++l) {
auto client = *l; auto client = *l;
if (isIrrelevant(client, c, desktop)) { if (isIrrelevant(client, window, desktop)) {
continue; continue;
} }
@ -317,7 +304,7 @@ void Placement::placeSmart(Window *c, const QRectF &area, PlacementPolicy /*next
// test the position of each window on the desk // test the position of each window on the desk
for (auto l = workspace()->stackingOrder().constBegin(); l != workspace()->stackingOrder().constEnd(); ++l) { for (auto l = workspace()->stackingOrder().constBegin(); l != workspace()->stackingOrder().constEnd(); ++l) {
auto client = *l; auto client = *l;
if (isIrrelevant(client, c, desktop)) { if (isIrrelevant(client, window, desktop)) {
continue; continue;
} }
@ -346,7 +333,7 @@ void Placement::placeSmart(Window *c, const QRectF &area, PlacementPolicy /*next
} }
// place the window // place the window
c->move(QPoint(x_optimal, y_optimal)); window->move(QPoint(x_optimal, y_optimal));
} }
void Placement::reinitCascading(int desktop) void Placement::reinitCascading(int desktop)
@ -384,71 +371,51 @@ void Placement::placeCascaded(Window *c, const QRect &area, PlacementPolicy next
return; return;
} }
/* cascadePlacement by Cristian Tibirna (tibirna@kde.org) (30Jan98)
*/
// work coords
int xp, yp;
// CT how do I get from the 'Client' class the size that NW squarish "handle" // CT how do I get from the 'Client' class the size that NW squarish "handle"
const QPoint delta = workspace()->cascadeOffset(c); const QPoint delta = workspace()->cascadeOffset(c);
const int dn = c->desktop() == 0 || c->isOnAllDesktops() ? (VirtualDesktopManager::self()->current() - 1) : (c->desktop() - 1); const int dn = c->desktop() == 0 || c->isOnAllDesktops() ? (VirtualDesktopManager::self()->current() - 1) : (c->desktop() - 1);
// initialize often used vars: width and height of c; we gain speed
const int ch = c->height();
const int cw = c->width();
const int X = area.left();
const int Y = area.top();
const int H = area.height();
const int W = area.width();
if (nextPlacement == PlacementUnknown) { if (nextPlacement == PlacementUnknown) {
nextPlacement = PlacementSmart; nextPlacement = PlacementSmart;
} }
// initialize if needed // initialize if needed
if (cci[dn].pos.x() < 0 || cci[dn].pos.x() < X || cci[dn].pos.y() < Y) { if (cci[dn].pos.x() < 0 || cci[dn].pos.x() < area.left() || cci[dn].pos.y() < area.top()) {
cci[dn].pos = QPoint(X, Y); cci[dn].pos = QPoint(area.left(), area.top());
cci[dn].col = cci[dn].row = 0; cci[dn].col = cci[dn].row = 0;
} }
xp = cci[dn].pos.x(); int xp = cci[dn].pos.x();
yp = cci[dn].pos.y(); int yp = cci[dn].pos.y();
// here to touch in case people vote for resize on placement // here to touch in case people vote for resize on placement
if ((yp + ch) > H) { if ((yp + c->height()) > area.height()) {
yp = Y; yp = area.top();
} }
if ((xp + cw) > W) { if ((xp + c->width()) > area.width()) {
if (!yp) { if (!yp) {
place(c, area, nextPlacement); place(c, area, nextPlacement);
return; return;
} else { } else {
xp = X; xp = area.left();
} }
} }
// if this isn't the first window // if this isn't the first window
if (cci[dn].pos.x() != X && cci[dn].pos.y() != Y) { if (cci[dn].pos.x() != area.left() && cci[dn].pos.y() != area.top()) {
/* The following statements cause an internal compiler error with if (xp != area.left() && yp == area.top()) {
* egcs-2.91.66 on SuSE Linux 6.3. The equivalent forms compile fine. cci[dn].col++;
* 22-Dec-1999 CS
*
* if (xp != X && yp == Y) xp = delta.x() * (++(cci[dn].col));
* if (yp != Y && xp == X) yp = delta.y() * (++(cci[dn].row));
*/
if (xp != X && yp == Y) {
++(cci[dn].col);
xp = delta.x() * cci[dn].col; xp = delta.x() * cci[dn].col;
} }
if (yp != Y && xp == X) { if (yp != area.top() && xp == area.left()) {
++(cci[dn].row); cci[dn].row++;
yp = delta.y() * cci[dn].row; yp = delta.y() * cci[dn].row;
} }
// last resort: if still doesn't fit, smart place it // last resort: if still doesn't fit, smart place it
if (((xp + cw) > W - X) || ((yp + ch) > H - Y)) { if (((xp + c->width()) > area.width() - area.left()) || ((yp + c->height()) > area.height() - area.top())) {
place(c, area, nextPlacement); place(c, area, nextPlacement);
return; return;
} }
@ -865,109 +832,109 @@ void Workspace::quickTileWindow(QuickTileMode mode)
m_activeWindow->setQuickTileMode(mode, true); m_activeWindow->setQuickTileMode(mode, true);
} }
qreal Workspace::packPositionLeft(const Window *client, qreal oldX, bool leftEdge) const qreal Workspace::packPositionLeft(const Window *window, qreal oldX, bool leftEdge) const
{ {
qreal newX = clientArea(MaximizeArea, client).left(); qreal newX = clientArea(MaximizeArea, window).left();
if (oldX <= newX) { // try another Xinerama screen if (oldX <= newX) { // try another Xinerama screen
newX = clientArea(MaximizeArea, newX = clientArea(MaximizeArea,
client, window,
QPointF(client->frameGeometry().left() - 1, client->frameGeometry().center().y())) QPointF(window->frameGeometry().left() - 1, window->frameGeometry().center().y()))
.left(); .left();
} }
if (oldX <= newX) { if (oldX <= newX) {
return oldX; return oldX;
} }
const int desktop = client->desktop() == 0 || client->isOnAllDesktops() ? VirtualDesktopManager::self()->current() : client->desktop(); VirtualDesktop *const desktop = window->isOnCurrentDesktop() ? VirtualDesktopManager::self()->currentDesktop() : window->desktops().front();
for (auto it = m_allClients.constBegin(), end = m_allClients.constEnd(); it != end; ++it) { for (auto it = m_allClients.constBegin(), end = m_allClients.constEnd(); it != end; ++it) {
if (isIrrelevant(*it, client, desktop)) { if (isIrrelevant(*it, window, desktop)) {
continue; continue;
} }
const qreal x = leftEdge ? (*it)->frameGeometry().right() : (*it)->frameGeometry().left() - 1; const qreal x = leftEdge ? (*it)->frameGeometry().right() : (*it)->frameGeometry().left() - 1;
if (x > newX && x < oldX if (x > newX && x < oldX
&& !(client->frameGeometry().top() > (*it)->frameGeometry().bottom() - 1 // they overlap in Y direction && !(window->frameGeometry().top() > (*it)->frameGeometry().bottom() - 1 // they overlap in Y direction
|| client->frameGeometry().bottom() - 1 < (*it)->frameGeometry().top())) { || window->frameGeometry().bottom() - 1 < (*it)->frameGeometry().top())) {
newX = x; newX = x;
} }
} }
return newX; return newX;
} }
qreal Workspace::packPositionRight(const Window *client, qreal oldX, bool rightEdge) const qreal Workspace::packPositionRight(const Window *window, qreal oldX, bool rightEdge) const
{ {
qreal newX = clientArea(MaximizeArea, client).right(); qreal newX = clientArea(MaximizeArea, window).right();
if (oldX >= newX) { // try another Xinerama screen if (oldX >= newX) { // try another Xinerama screen
newX = clientArea(MaximizeArea, newX = clientArea(MaximizeArea,
client, window,
QPointF(client->frameGeometry().right(), client->frameGeometry().center().y())) QPointF(window->frameGeometry().right(), window->frameGeometry().center().y()))
.right(); .right();
} }
if (oldX >= newX) { if (oldX >= newX) {
return oldX; return oldX;
} }
const int desktop = client->desktop() == 0 || client->isOnAllDesktops() ? VirtualDesktopManager::self()->current() : client->desktop(); VirtualDesktop *const desktop = window->isOnCurrentDesktop() ? VirtualDesktopManager::self()->currentDesktop() : window->desktops().front();
for (auto it = m_allClients.constBegin(), end = m_allClients.constEnd(); it != end; ++it) { for (auto it = m_allClients.constBegin(), end = m_allClients.constEnd(); it != end; ++it) {
if (isIrrelevant(*it, client, desktop)) { if (isIrrelevant(*it, window, desktop)) {
continue; continue;
} }
const qreal x = rightEdge ? (*it)->frameGeometry().left() : (*it)->frameGeometry().right() + 1; const qreal x = rightEdge ? (*it)->frameGeometry().left() : (*it)->frameGeometry().right() + 1;
if (x < newX && x > oldX if (x < newX && x > oldX
&& !(client->frameGeometry().top() > (*it)->frameGeometry().bottom() - 1 && !(window->frameGeometry().top() > (*it)->frameGeometry().bottom() - 1
|| client->frameGeometry().bottom() - 1 < (*it)->frameGeometry().top())) { || window->frameGeometry().bottom() - 1 < (*it)->frameGeometry().top())) {
newX = x; newX = x;
} }
} }
return newX; return newX;
} }
qreal Workspace::packPositionUp(const Window *client, qreal oldY, bool topEdge) const qreal Workspace::packPositionUp(const Window *window, qreal oldY, bool topEdge) const
{ {
qreal newY = clientArea(MaximizeArea, client).top(); qreal newY = clientArea(MaximizeArea, window).top();
if (oldY <= newY) { // try another Xinerama screen if (oldY <= newY) { // try another Xinerama screen
newY = clientArea(MaximizeArea, newY = clientArea(MaximizeArea,
client, window,
QPointF(client->frameGeometry().center().x(), client->frameGeometry().top() - 1)) QPointF(window->frameGeometry().center().x(), window->frameGeometry().top() - 1))
.top(); .top();
} }
if (oldY <= newY) { if (oldY <= newY) {
return oldY; return oldY;
} }
const int desktop = client->desktop() == 0 || client->isOnAllDesktops() ? VirtualDesktopManager::self()->current() : client->desktop(); VirtualDesktop *const desktop = window->isOnCurrentDesktop() ? VirtualDesktopManager::self()->currentDesktop() : window->desktops().front();
for (auto it = m_allClients.constBegin(), end = m_allClients.constEnd(); it != end; ++it) { for (auto it = m_allClients.constBegin(), end = m_allClients.constEnd(); it != end; ++it) {
if (isIrrelevant(*it, client, desktop)) { if (isIrrelevant(*it, window, desktop)) {
continue; continue;
} }
const qreal y = topEdge ? (*it)->frameGeometry().bottom() : (*it)->frameGeometry().top() - 1; const qreal y = topEdge ? (*it)->frameGeometry().bottom() : (*it)->frameGeometry().top() - 1;
if (y > newY && y < oldY if (y > newY && y < oldY
&& !(client->frameGeometry().left() > (*it)->frameGeometry().right() - 1 // they overlap in X direction && !(window->frameGeometry().left() > (*it)->frameGeometry().right() - 1 // they overlap in X direction
|| client->frameGeometry().right() - 1 < (*it)->frameGeometry().left())) { || window->frameGeometry().right() - 1 < (*it)->frameGeometry().left())) {
newY = y; newY = y;
} }
} }
return newY; return newY;
} }
qreal Workspace::packPositionDown(const Window *client, qreal oldY, bool bottomEdge) const qreal Workspace::packPositionDown(const Window *window, qreal oldY, bool bottomEdge) const
{ {
qreal newY = clientArea(MaximizeArea, client).bottom(); qreal newY = clientArea(MaximizeArea, window).bottom();
if (oldY >= newY) { // try another Xinerama screen if (oldY >= newY) { // try another Xinerama screen
newY = clientArea(MaximizeArea, newY = clientArea(MaximizeArea,
client, window,
QPointF(client->frameGeometry().center().x(), client->frameGeometry().bottom())) QPointF(window->frameGeometry().center().x(), window->frameGeometry().bottom()))
.bottom(); .bottom();
} }
if (oldY >= newY) { if (oldY >= newY) {
return oldY; return oldY;
} }
const int desktop = client->desktop() == 0 || client->isOnAllDesktops() ? VirtualDesktopManager::self()->current() : client->desktop(); VirtualDesktop *const desktop = window->isOnCurrentDesktop() ? VirtualDesktopManager::self()->currentDesktop() : window->desktops().front();
for (auto it = m_allClients.constBegin(), end = m_allClients.constEnd(); it != end; ++it) { for (auto it = m_allClients.constBegin(), end = m_allClients.constEnd(); it != end; ++it) {
if (isIrrelevant(*it, client, desktop)) { if (isIrrelevant(*it, window, desktop)) {
continue; continue;
} }
const qreal y = bottomEdge ? (*it)->frameGeometry().top() : (*it)->frameGeometry().bottom() + 1; const qreal y = bottomEdge ? (*it)->frameGeometry().top() : (*it)->frameGeometry().bottom() + 1;
if (y < newY && y > oldY if (y < newY && y > oldY
&& !(client->frameGeometry().left() > (*it)->frameGeometry().right() - 1 && !(window->frameGeometry().left() > (*it)->frameGeometry().right() - 1
|| client->frameGeometry().right() - 1 < (*it)->frameGeometry().left())) { || window->frameGeometry().right() - 1 < (*it)->frameGeometry().left())) {
newY = y; newY = y;
} }
} }