Preserve relative order of transient siblings
If a constraint indicates that window A must be below window B but it's not the case at the moment, the workspace will move window A right after window B. This can invert the relative order of transient siblings, for example let's say that there are three constraints - A <- B (window A must be below window B) - A <- C - A <- D and the unconstrained stacking order looks as follows: [B, C, D, A]. The final constrained stacking order is expected to look as [A, B, C, D], but currently it's [A, D, C, B] instead: - starting stacking order: [B, C, D, A] - apply A <- B constraint: [C, D, A, B] - apply A <- C constraint: [D, A, C, B] - apply A <- D constraint: [A, D, C, B] In order to fix this issue, this patch makes the workspace traverse the constraint graph in the reverse order. In addition to that, it ensures that the relative order of transient siblings in unconstrained stacking order is preserved in the constrained one. BUG: 477262
This commit is contained in:
parent
41df430aa8
commit
15b8fbe604
1 changed files with 16 additions and 7 deletions
|
@ -82,7 +82,6 @@
|
|||
#include <array>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QQueue>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
@ -541,22 +540,28 @@ QList<Window *> Workspace::constrainedStackingOrder()
|
|||
|
||||
// Apply the stacking order constraints. First, we enqueue the root constraints, i.e.
|
||||
// the ones that are not affected by other constraints.
|
||||
QQueue<Constraint *> constraints;
|
||||
QList<Constraint *> constraints;
|
||||
constraints.reserve(m_constraints.count());
|
||||
for (Constraint *constraint : std::as_const(m_constraints)) {
|
||||
if (constraint->parents.isEmpty()) {
|
||||
constraint->enqueued = true;
|
||||
constraints.enqueue(constraint);
|
||||
constraints.append(constraint);
|
||||
} else {
|
||||
constraint->enqueued = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Preserve the relative order of transient siblings in the unconstrained stacking order.
|
||||
auto constraintComparator = [&stacking](Constraint *a, Constraint *b) {
|
||||
return stacking.indexOf(a->above) > stacking.indexOf(b->above);
|
||||
};
|
||||
std::sort(constraints.begin(), constraints.end(), constraintComparator);
|
||||
|
||||
// Once we've enqueued all the root constraints, we traverse the constraints tree in
|
||||
// the breadth-first search fashion. A constraint is applied only if its condition is
|
||||
// the reverse breadth-first search fashion. A constraint is applied only if its condition is
|
||||
// not met.
|
||||
while (!constraints.isEmpty()) {
|
||||
Constraint *constraint = constraints.dequeue();
|
||||
Constraint *constraint = constraints.takeFirst();
|
||||
|
||||
const int belowIndex = stacking.indexOf(constraint->below);
|
||||
const int aboveIndex = stacking.indexOf(constraint->above);
|
||||
|
@ -567,10 +572,14 @@ QList<Window *> Workspace::constrainedStackingOrder()
|
|||
stacking.insert(belowIndex, constraint->above);
|
||||
}
|
||||
|
||||
for (Constraint *child : std::as_const(constraint->children)) {
|
||||
// Preserve the relative order of transient siblings in the unconstrained stacking order.
|
||||
QList<Constraint *> children = constraint->children;
|
||||
std::sort(children.begin(), children.end(), constraintComparator);
|
||||
|
||||
for (Constraint *child : std::as_const(children)) {
|
||||
if (!child->enqueued) {
|
||||
child->enqueued = true;
|
||||
constraints.enqueue(child);
|
||||
constraints.append(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue