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:
parent
8197bf8890
commit
147f3509ea
1 changed files with 64 additions and 97 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue